MVVM kominikacja między warstwami. Brak wartości po bindowaniu

0

Witajcie, proszę o pomoc, bo zaraz mnie coś trafi....

Próbuję zbindować do widoku wartości właściwość z obiektu klasy CCOM.

Mam w Model deklarację klasy obiekt CCOMport:

namespace PortaBarcode.Model
{
       class CCOMport
       {
             private int _baudRate;
             public int BaudRate { get; set; }
             private int _dataBits;
             public int DataBits { get; set; }
             private string _portName;
             public string PortName { get; set; }
       }
}

Potem w ModelView mam klasę KonfiguracjaPortuViewModel.W tej klasie tworzę obiekt klasy CCOMport i ustawiam wartość port_COM.BaudRate. Następnie chcę zbindować tą właściwość w widoku (kod niżej). Chodzi o właściwość BaudRate. Jeżeli przekazuję właściwość klasy KonfiguracjaPortuViewModel, czyli MyProperty to bindowanie działa ładnie i wyświetlana jest wartość. A problem jest z obiektem klasy CCOmport. Może nie wiem jak ustawić datacontext na obiekty. 

<b>ViewModel</b>:
```csharp
namespace PortaBarcode.ViewModel
{      
       class KonfiguracjaPortuViewModel
       {
             public int MyProperty { get; set; }
             public CCOMport port_COM;

public KonfiguracjaPortuViewModel()
             {
                    MyProperty = 1111;
                    port_COM = new CCOMport();
                    port_COM.BaudRate = 2222222;
             }            
       }
}

W code behind widoku ustawiam datacontext na :

this.admin_pass_grid.DataContext = new KonfiguracjaPortuViewModel();

Jest to datacontext od grida
View:

<Grid Name="admin_pass_grid">
<WrapPanel>
<Label Width="50" Margin="2,3,5,3">ID:</Label>
<TextBox  Name="barcode_manual_text" Margin="5,3,5,3" Width="100" 
         Background="Wheat" Text="{Binding port_COM}" ></TextBox>
</WrapPanel>
</Grid>

Próbowałem też ustawiać datacontext textboxa na klasę z ViewModel, ale to też nie pomagało:
this.barcode_manual_text.DataContext = new KonfiguracjaPortuViewModel();

Przypominam , że z właściwością MyProperty klasy konfiguracja portu zadziałało poprawnie.

Zadziałało dopiero po ustawieniu dziedziczenia klasy KonfiguracjaPortuViewModel : CCOMport , no ale to przecież jest niezgodne z wzorcem. Co będzie jak będę używał kilku różnych obiektów i będę chciał wyświetlać wyniki w widoku?

Czy dla każdego wyświetlanego elementu w widoku trzeba tworzyć oddzielne właściwości w wartwie ViewModel?

Dzięki za pomoc.

Maciej

0

Twój ViewModel dla widoku modelu COMPort, ma właściwość(zmienną?) port_COM (dodaj getter i setter);
Czyli w widoku bindujesz tak: {Binding port_COM.BaudRate }

I gdzieś, gdzie tworzysz okno widoku (zakładając że okno nazywa się COMWindow):

COMWindow view = new COMWindow();
view.DataContext = new COMWindowViewModel();
view.ShowDialog();

Dodatkowo później, jeśli Twój ViewModel będzie zmieniać dynamicznie bindowane właściwości (np. jakaś akcja guzika), to musisz implementować INotiifyPropertyChanged.

0
maciejmt napisał(a):

Twój ViewModel dla widoku modelu COMPort, ma właściwość(zmienną?) port_COM (dodaj getter i setter);
Czyli w widoku bindujesz tak: {Binding port_COM.BaudRate }

Tak też robiłem (zapomniałem dopisać). I nie działa. Sprawdziłem dzisiaj jeszcze raz. Tak wygląda część kodu w warstwie ViewModel

class KonfiguracjaPortuViewModel
    {
        CCOMport port_com { get; set; }
      
  public KonfiguracjaPortuViewModel()
        {
            port_com = new CCOMport();
            port_com.BaudRate = 2222222;            
        }
(...)

Ale jak ustawie tak:

class KonfiguracjaPortuViewModel
    {
        string _property{ get; set; }
      
  public KonfiguracjaPortuViewModel()
        {
            _property = "2222";            
        }
(...)

, to wyświetla ładnie w textbox'ie.

maciejmt napisał(a):

Dodatkowo później, jeśli Twój ViewModel będzie zmieniać dynamicznie bindowane właściwości (np. jakaś akcja guzika), to musisz implementować INotiifyPropertyChanged.

Dzięki, pamiętam o tym interfejsie. Ale u mnie bindowanie jest tylko przy uruchomieniu w jedną stroną. Chodzi o przedstawienie wyniku na ekranie. Nie potrzebuje w tym przypadku INotifyPropertyChanged.

0

po pierwsze

             private int _baudRate;
             public int BaudRate { get; set; }

tworzysz prywatne zmienne i publiczne automatyczne własności które z nich nie korzystają - na pewno nie mylisz się w kodzie podczas ustawiania?

po drugie, co chcesz wyświetlić? jeśli zbindujesz do CCOMport to jest to obiekt i nie wyświetli się na pewno nic dobrego dopóki nie przeciążysz metody ToString() tego obiektu, albo nie zbindujesz do konkretnej własności jak na przykład {Binding port_COM.PortName}

po trzecie skorzystaj z frameworka Caliburn.Micro - ułatwi Ci to znacznie pracę, w ogóle będziesz mógł zapomnieć o ustawianiu DataContext - wystarczy że tak samo nazwiesz kontrolkę w widoku i własność w viewmodel i własność się automagicznie zbinduje bez żadnego kodu

0
ggdfsg napisał(a):

po pierwsze
po drugie, co chcesz wyświetlić? jeśli zbindujesz do CCOMport to jest to obiekt i nie wyświetli się na pewno nic dobrego dopóki nie przeciążysz metody ToString() tego obiektu, albo nie zbindujesz do konkretnej własności jak na przykład {Binding port_COM.PortName}

tak, sorry, oczywiście binduje określoną właściwość - zapomniałem dopisać w poprzednim poście:

 <TextBox  Name="barcode_manual_text" Margin="5,3,5,3" Width="100" Background="Wheat" Text="{Binding Port_com.PortName}" ></TextBox>

Słuchajcie , pomogło jak ustawiłem get i set w dla obiektu.** Czy tak się powinno robić w MVVM? **

    class KonfiguracjaPortuViewModel 
    {
        private CCOMport _port_com ;

        public CCOMport Port_com { 
            get { return _port_com; }
            set { _port_com = value; }
        }        
        public KonfiguracjaPortuViewModel()
        {
            Port_com = new CCOMport();
            Port_com.PortNumber = "sdsdss";            
          
0

Tak sie nigdy nie powinno robic, niezaleznie od wzorca/frameworka/kij wie co. Po prostu takie dzialanie jest bezsensowne.
Zamiast:

private int _somePrivateVariable;
public int SomePublicProperty
{
  get { return _somePrivateVariable; }
  set { _somePrivateVariable = value; }
}

mozna zrobic:

public int SomePublicProperty { get; set; }

Kompilator sam wygeneruje odpowiednie zmienne, metody oraz ciala tych metod.

Druga sprawa to nie stosujesz konwencji C#.

0

można tworzyć jeden i drugi zapis dla właściwości danej klasy. Jak kolega ma jakieś propozycje do rozwiązania mojego problemy z bindowaniem, to proszę odpowiedzi związane z tematem.

0

ok, przejrzałem jeszcze raz wątek i zmieniłem zapis na :

public CCOMport Port_com    {get;set;}

tak jak kolega wcześniej zauważył:

maciejmt napisał(a):

Twój ViewModel dla widoku modelu COMPort, ma właściwość(zmienną?) port_COM (dodaj getter i setter);
Czyli w widoku bindujesz tak: {Binding port_COM.BaudRate }

Nadal działa. Czyli błędy jakie wykonałem, to obiekt klasy powinien być publiczny (brak modyfikatora dostępu automatycznie ustawia jako prywatny) po drugie brak gettera i settera, a obiekt klasy z warstwy Modelu powinien być traktowany jako właściwość w klasie wyżej, czyli ViewModelu.

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