C# WPF Adat kötés probléma MVPVM mintában

C# WPF Adat kötés probléma MVPVM mintában
2016-01-11T14:16:40+01:00
2016-01-12T10:29:43+01:00
2022-08-18T11:05:33+02:00
Enderpt
Sziasztok!

Már pár napja küzdök az alábbi DataBinding problémával, és a Google által kiadott majdnem összes verziót kipróbáltam már (azért majdnem összeset, mert a jó megoldás még nincs meg).
Van egy MVPVM minta alapján készült WinForms program, amit WPF-re igyekszem átírni.
Jórész működik is (login, dokkolás), azonban egy lista (ObservableCollection) semmiképp nem akar megjelenni a Listview-ban. Debug módban látszik, hogy tartalmazza az ItemSource a listát (), mert a count eredménye 89, de nem jelenik meg a Listview-ban:

A ViewModellben:

public FigyelmeztetesekViewModel(FigyelmeztetesekView app) { figy_app = app; ... figy_app.DTGfigyelm.ItemsSource = figyelmeztetesek; }
private ObservableCollection<FigyelmeztetesDTO> figyelmeztetesek; 

public ObservableCollection<FigyelmeztetesDTO> Figyelmeztetesek 
{
     get { return this.figyelmeztetesek; }
     set
     {
         this.figyelmeztetesek = value;
         this.NotifyPropertyChanged("figyelmeztetesek");
     }
}
A XAML (View):

<ListView x:Name="DTGfigyelm" Margin="1,101,1,1" Visibility="Visible" DataContext="{Binding Figyelmeztetesek}"> <ListView.View> <GridView> <GridViewColumn Width="auto" Header="Ügyfél" DisplayMemberBinding="{Binding Ugyfel}"/> <GridViewColumn Width="auto" Header="Figyelmeztetés" DisplayMemberBinding="{Binding EsemenyIdeje}"/> <GridViewColumn Width="auto" Header="Rögzítette" DisplayMemberBinding="{Binding Rogzitette}"/> <GridViewColumn Width="auto" Header="Státusz" DisplayMemberBinding="{Binding UgyStatusz}"/> </GridView> </ListView.View> </ListView>
Mutasd a teljes hozzászólást!
De most hogy jön ide  a prezeneter????????

Eddig volt View és ViewModel, most akkor mi a fenének a presenter.

Valahol a kódban:

var view = View(); var viewModel = new ViewModel(figyelmeztetesek); view.DataContext = viewModel;
A figyelmezetetések az egy collection lista, vagy observable... a ViewModel-ben betoltod az itemjeit, a observable collectionbe.  Ha az normalisan be van bindolva, azaz úgy ahogy én csináltam (ItemsSource = {Binding Figye...}), akkor annak működnie kell, ennyit kéne csinálni....

A kód amit küldtem az jó, kb. 5 perc alatt dobtam össze. Rakj össze egy ilyen sample appot, és teszteld ki próbálgasd meg. Ha ott megy, akkor már valszeg tiszta lesz mit bajszinottál el a főkódban...
Mutasd a teljes hozzászólást!

  • ObservableCollection-ökkel van egy kis probléma....

    Ha cseréled az instance-ot akkor a bind elvész.

    Tehtá nem az instanceot kell cserélni, hanem a régi Itemeket törölni (Clear), majd az új Itemeket, hozzá Add-olni.

    Üdv

    public partial class MainWindow : Window { public ObservableCollection<string> Figyelmeztetesek { get; set; } public MainWindow() { InitializeComponent(); Figyelmeztetesek = new ObservableCollection<string>(); Figyelmeztetesek.Add("Nanan"); Figyelmeztetesek.Add("Nanan"); Figyelmeztetesek.Add("Nanan"); Figyelmeztetesek.Add("Nanan"); Figyelmeztetesek.Add("Nanan"); DataContext = this; } } <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <ListView ItemsSource="{Binding Figyelmeztetesek}"/> </Grid> </Window>
    Mutasd a teljes hozzászólást!
  • Ha cseréled az instance-ot akkor a bind elvész.

    ez így ebben a formában nem igaz

    Enderpt
    a ListView-nak ne a DataContext tulajdonságát állítsd be, hanem ahogy Elvira is csinálta az ItemsSource-t
    Mutasd a teljes hozzászólást!
  • Ok valóban nem vész el a bind, de "használhatatlan" lesz...

    A common mistake is to modify the parent object’s property and replace one ObservableCollection with another. Just about every person who uses ObservableCollections makes this mistake at least once. EvenScott Hanselman made this mistake on stage at Mix ‘09 (skip to 10:30). The problem is that after you swap out one ObservableCollection for a new one, the view is still bound to the old one.

    Természetesen ha eltüzel a ProeprtyChanegd eventet, akkor le fog cserélődni az instance...
    Mutasd a teljes hozzászólást!
  • ItemSourc-al sem jó

    public class FigyelmeztetesekViewModel : ViewModelBase, IFigyelmeztetesekView { private FigyelmeztetesekView figy_app = null; public FigyelmeztetesekViewModel(FigyelmeztetesekView app) { figy_app = app; ... figy_app.DataContext = this; } private ObservableCollection<FigyelmeztetesDTO> figyelmeztetesek; public ObservableCollection<FigyelmeztetesDTO> Figyelmeztetesek { get { return this.figyelmeztetesek; } set { this.figyelmeztetesek = value; this.NotifyPropertyChanged("Figyelmeztetesek"); } } }
    XAML (a MainWindow.xaml egy külön file amiben a dokkolás van (avalondock) abba illeszkedik 9 egyéb Tab, amiből ez az egyik):

    <Grid x:Class="Program.WPF.GUI.View.FigyelmeztetesekView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" Height="auto" Width="auto" MinWidth="300" MinHeight="400"> <ListView x:Name="DTGfigyelm" Margin="1,101,1,1" Visibility="Visible" ItemsSource="{Binding Figyelmeztetesek}"> <ListView.View> <GridView> <GridViewColumn Width="auto" Header="Ügyfél" DisplayMemberBinding="{Binding Ugyfel}"/> <GridViewColumn Width="auto" Header="Figyelmeztetés" DisplayMemberBinding="{Binding EsemenyIdeje}"/> <GridViewColumn Width="auto" Header="Rögzítette" DisplayMemberBinding="{Binding Rogzitette}"/> <GridViewColumn Width="auto" Header="Státusz" DisplayMemberBinding="{Binding UgyStatusz}"/> </GridView> </ListView.View> </ListView> </Grid>
    Mutasd a teljes hozzászólást!
  • nagy eséllyel azért, mert a DataContext sehol sincs beállítva
    az oldaladnak biztos van egy mögötted kódja, amiben a ViewModelt példányosítod
    na ott kéne
    DataContext = viewmodel
    Mutasd a teljes hozzászólást!
  • Mondjuk itt?

    public DokumentumokView DocViewWin = new DokumentumokView(); public FigyelmeztetesekView FigyViewWin = new FigyelmeztetesekView(); public MainWindow() { InitializeComponent(); DocViewWin.DataContext = new DokumentumokViewModel(DocViewWin); FigyViewWin.DataContext = new FigyelmeztetesekViewModel(FigyViewWin); }
    Ez is van mégse akarja az igatat, MVVM patternel készült progiban működő megoldást tettem ide, de itt nem ment valamiért, azóta már nem is tudom mennyiszer írtam át
    Mutasd a teljes hozzászólást!
  • A ViewModel (VM) ne tudjon a View-ról... Ahol Viewt, létrehozod, ott kötöd be a DataContext-be a VM-et.

    A Figyelmeztetesek Collection lett peldányosítva?

    public partial class MainWindow : Window { public ObservableCollection<FigyelmeztetesDTO> Figyelmeztetesek { get; set; } public MainWindow() { InitializeComponent(); Figyelmeztetesek = new ObservableCollection<FigyelmeztetesDTO>(); Figyelmeztetesek.Add(new FigyelmeztetesDTO { Ugyfel = "En", EsemenyIdeje = DateTime.Now, Rogzitette = "Te", UgyStatusz = FigyelmeztetesDTO.UgyStatuszEnum.Folyamataban }); DataContext = this; } public class FigyelmeztetesDTO { public string Ugyfel { get; set; } public DateTime EsemenyIdeje { get; set; } public string Rogzitette { get; set; } public UgyStatuszEnum UgyStatusz { get; set; } public enum UgyStatuszEnum { Folyamataban, Kesz } } } <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <ListView ItemsSource="{Binding Figyelmeztetesek}"> <ListView.View> <GridView> <GridViewColumn Width="auto" Header="Ügyfél" DisplayMemberBinding="{Binding Ugyfel}"/> <GridViewColumn Width="auto" Header="Figyelmeztetés" DisplayMemberBinding="{Binding EsemenyIdeje}"/> <GridViewColumn Width="auto" Header="Rögzítette" DisplayMemberBinding="{Binding Rogzitette}"/> <GridViewColumn Width="auto" Header="Státusz" DisplayMemberBinding="{Binding UgyStatusz}"/> </GridView> </ListView.View> </ListView> </Grid> </Window>
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • A class FigyelmeztetesekDTO -nak nem kéne implementálnia az INotifyPropertyChanged-t?
    Mutasd a teljes hozzászólást!
  • Ha nem változik az objektum tartalma, miután  a collectionhöz adod, akkor nem...
    Mutasd a teljes hozzászólást!
  • Az a collection van inicializálva, tettél bele figyelmeztetést? Vagy tök üres, vagy nincs is létrehozva?
    Mutasd a teljes hozzászólást!
  • A collection (count = 89 tehát van benne 89 sor) a presenterben van példányosítva, ami viszont

    Az objektumhivatkozás nincs beállítva semmilyen objektumpéldányra
    hibával leáll, ha a ViewModell nem kapja meg a View példányát, mert a presentert a view-ra kell meghívni:

    public class FigyelmeztetesekPresenter : PresenterBase { public void FigyelmezteteseketBetolt() { this.FigyelmeztetesekView.Kurzor = Egerkurzorok.Varakozo; try { this.FigyelmeztetesekView.Figyelmeztetesek = new ObservableCollection<FigyelmeztetesDTO>(this.dal.FigyelmezteteseketLekerdez(this.FigyelmeztetesekView.IdolimitHetek)); } catch (Exception ex) { this.FigyelmeztetesekView.Uzenet(ex.Message); } this.FigyelmeztetesekView.Kurzor = Egerkurzorok.Normal; } }
    Mutasd a teljes hozzászólást!
  • A ListView-nak mar probaltal ItemTemplatet csinalni?
    ItemsControl.ItemTemplate Property (System.Windows.Controls)
    Mutasd a teljes hozzászólást!
  • De most hogy jön ide  a prezeneter????????

    Eddig volt View és ViewModel, most akkor mi a fenének a presenter.

    Valahol a kódban:

    var view = View(); var viewModel = new ViewModel(figyelmeztetesek); view.DataContext = viewModel;
    A figyelmezetetések az egy collection lista, vagy observable... a ViewModel-ben betoltod az itemjeit, a observable collectionbe.  Ha az normalisan be van bindolva, azaz úgy ahogy én csináltam (ItemsSource = {Binding Figye...}), akkor annak működnie kell, ennyit kéne csinálni....

    A kód amit küldtem az jó, kb. 5 perc alatt dobtam össze. Rakj össze egy ilyen sample appot, és teszteld ki próbálgasd meg. Ha ott megy, akkor már valszeg tiszta lesz mit bajszinottál el a főkódban...
    Mutasd a teljes hozzászólást!
  • Elvira:  
    Mint említettem egy valaki álltal WinForms-ban megírt kész programot kell átírnom WPF-re, ami MVPVM patternnel készült és így is kell maradjon; 11 projektből áll és nekem csak 1-hez van módosítási jogom.
    A főablak MainWindow, ebben van az ablakok dokkolása, hogy át lehessen helyezni bárhová (mint a VS-ablakait), ebben van a template és itt vannak becsatolva a további ablakok (View-k), de a tényleges munkának a ViewModel-ben illetve a Presenterben kell történnie.
    Ha a ViewModell nem kapja meg a view object-et, akkor a presenter nem fogja megtalálni a lekérdezésekhez szükséges mezőket.
    Neten találtam kb 2 tucat example-t és sample-t, amik működnek is, amikor új tesztproject-ként megcsinálom, illetve nekem is van 2 saját program, amiben működik az adatkötés, de egyik megoldással sem működik EBBEN.

    pret83: Kösz, még nem próbáltam, de ki fogom próbálni még ma.

    sg81: lehet igazad van és ott lesz a kutya elásva, most hogy jobban megnéztem egy MVVM-el készült progimat.
    Mutasd a teljes hozzászólást!
abcd