Bindowanie userControls z danymi

0

Witam,

Zeby nie pisać ściany tekstu, opisze problem pokrótce. Oto co chce zrobić:

Głowne okno aplikacji desktopowej składa się miedzy innymi z kilku dośc specyficznych kontrolek. Kontrolki przyjmuja pewne dane, jakoś je tam obrabiają/walidują/formatuja i prezentują w określony sposób. Wymyśliłem, że całą logike kontrolek zamkne w obiektach userControl, na zewnątrz wystawie pewne DependencyProperties, w klasie głównego okna bede tworzył viewModele per kontrolka i własności tych modeli bede bindował z dependency properties kontrolek. Jednak tutaj zaczęły sie schody, bo nie działa to tak, jak myślałem, że bedzie dzialać ;)

Zrobiłem przykładową kontrolke, przykładowy viewModel z wykorzystaniem INotifyPropertyChanged, binduje jakis tam przykładowy property. Po stworzeniu obiektu w konstruktorze głównego okna dane są odświeżane:

public MainWindow()
        {
            InitializeComponent();
            FirstViewModel = new SimpleControlViewModel()
            {
                TextToBind = "SampleText"
            };
            this.DataContext = this;
        }

jednak kiedy zmienie property viewModelu z innego miejsca, np kliknieciem buttona:

this.FirstViewModel.TextToBind = "xxx";

to zmiana ta nie jest odwzorowana na gui. Dodam, że property które zmieniam (TextToBind) odpala odpowiedni event. Dodałem przykładowy projekt w załączniku, zeby bardziej zobrazować problem. Jakiś czas temu pomogli mi @Ktos i @DibbyDum, może i tym razem rzucicie na to okiem?:D

1

Dodaj w xaml'u Binding.Mode na TwoWay przykład:

<Controls:SimpleControl x:Name="SimpleCtrl1" CustomText="{Binding FirstViewModel.TextToBind, Mode=TwoWay}" Margin="0,0,0,291" />

analogicznie będzie w drugim.

0
DibbyDum napisał(a):

Dodaj w xaml'u Binding.Mode na TwoWay przykład:

<Controls:SimpleControl x:Name="SimpleCtrl1" CustomText="{Binding FirstViewModel.TextToBind, Mode=TwoWay}" Margin="0,0,0,291" />

analogicznie będzie w drugim.

Dzieki, działa super;) Moglbys jednak wyjaśnić dlaczego to działa? Nie bardzo to rozumiem... Myslalem, ze mode TwoWay jets po to, zeby np zmieniajac coś na gui, updatował sie też zbindowany ViewModel. Tutaj jednak zmieniam bezpośrednio property na ViewModelu wiec binding powinien zachodzic w kierunku model->gui. Tak to jest, czy namieszałem?;p

0

Nie jestem do końca pewien ale tutaj zachodzi następująca rzecz podczas Binding.Mode = TwoWay

  1. Zmieniasz dane w ViewModelu
  2. ViewModel informuje o tym View
  3. View odpowiada zostałem zmieniony
  4. O zmianie informacja dochodzi do ViewModel jak i do CustomControl i tylko w taki sposób jesteś w stanie poinformować CustomControl że wartość się zmieniła.
    Więc robisz komunikację ViewModel <-> gui -> CustomControl.

Pewnie znalazły by się jakieś czary mary które robią tą inaczej ale tak jest najprościej. ;)

0

Masz rację, powinno wystarczyć "OneWay" i tak jest w większości kontrolek
Ale w przypadku CustomControls "OneWay" tak naprawdę znaczy "OneTime" binding - bindowanie zostaje podmienione na wartość i natychmiast usunięte

Tak się nie dzieje w przypadku bindowania "TwoWay" które można ustawić domyślnie:

new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(pixelPerProbePropertyChanged))

szczerze mówiąc nie rozumiem do końca dlaczego OneWay jest w ten sposób traktowane w przypadku customowych kontrolek

1

ok, więc problemem była ta linia:

endView.CustomText = args.NewValue.ToString();

wywoływała ona setter na którym było:

SetValue(CustomTextProperty, value);

co zastępowało bindowanie zwykłą wartością

po zastąpieniu wspomnianej linii linijką:

 endView.tbName.Text = endView.CustomText + "ss";

wszystko działa, nawet po ustawieniu Mode=OneWay

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0