Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
DataGidView DataBinding WPF wahrscheinlich Verständnisproblem
Sindelfinger
myCSharp.de - Member



Dabei seit:
Beiträge: 22
Herkunft: Deutschland

Themenstarter:

DataGidView DataBinding WPF wahrscheinlich Verständnisproblem

beantworten | zitieren | melden

Liebes Forum,

derzeit bin ich dabei, eine WinForms - Anwendung ein bißchen aufzuhübschen und auf WPF zu übertragen. Im alten Projekt habe ich mir im Hauptbildschirm Spielstände mitgeschrieben in eine dort lokale Liste die aus Einträgen meiner Klasse(das Types böse sind, habe ich hier im Forum gelernt :D) "MatchHistory" besteht.

Dann das Ganze über die Schnittstelle in mein Ergebnisformular geladen und dort mit einer ListView angezeigt. So weit - so gut.

Der neue Plan ist das ganze mit einem DataGridView anzuzeigen, das aber eine Datenbindung zu dieser Klasse hat.

In diesem Beitrag wurde das Thema angeschnitten und ich habe nach diesem Muster eine MatchHistoryViewModel - Klasse erstellt.

Jetzt fehlt mir wohl nur noch ein kleines Stück:

Ich habe eine lokale Variable vom Typen dieser Klasse erstellt:


private MatchHistoryViewModel _myMatchView = new MatchHistoryViewModel(); 
public MatchHistoryViewModel myMatchView
{
     get { return _myMatchView; }
     set 
     {
          _myMatchView = value;
     }
}


Beim Starten meines MainWindows füttere ich das mit Daten:

 
private void Test2()
{         
    foreach (string s in Enum.GetNames(typeof(MatchNames)))
   {
         MatchViewModel mv = new MatchViewModel
         { 
                ID=0,
                GameName=s,
                Sets2Play=3,
                SetsPlayed=0,
                Score0=0,
                Score1=0,
                Player1="Vika",
                Player2="Roli"
          };
          _myMatchView.AddEntry(mv);
     }
        
}

Anhand des Beispiels in dem o.a. Artikel habe ich dann versucht, die Bindung herzustellen.
<Window x:Class="ListViewBinding.MainWindow"   
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MatchHistoryViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <DataGrid x:Name="Match" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding _myMatchview}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Width="50" Binding="{Binding ID}"/>
                <DataGridTextColumn Header="Game" Width="150" Binding="{Binding GameName}"/>
                <DataGridTextColumn Header="Sets" Width="100" Binding="{Binding Sets2Play}"/>
                <DataGridTextColumn Header="Played" Width="100" Binding="{Binding SetsPlayed}"/>
            </DataGrid.Columns>
        </DataGrid>

Aber da kommt die Fehlermeldung:
Fehler
Schweregrad Anzahl Datenkontext Bindungspfad Ziel Zieltyp Beschreibung Datei Zeile Projekt
Fehler 1 MatchHistoryViewModel _myMatchview DataGrid.ItemsSource, Name="Match" IEnumerable Die Eigenschaft "_myMatchview" wurde im Objekt vom Typ "MatchHistoryViewModel" nicht gefunden.

Es ist ja nicht so, daß es ich das dringend brauche. Aber verstehen möchte ich das Ganze endlich. Wahrscheinlich ist der Denkfehler riesig oder winzig.

Und nach der zweiten schlaflosen Nacht deswegen gehe ich jetzt heia.

Off Topic: Für alle ein gesundes neues Jahr.
2 stupid 4 chess? No way.
2 stupid 4 C#? It seems so X(
private Nachricht | Beiträge des Benutzers
Urza
myCSharp.de - Member



Dabei seit:
Beiträge: 43

beantworten | zitieren | melden

_myMatchview kann nicht gefunden werden weil es private ist.
Du musst an myMatchview binden.
Das solltest du auch noch nach MyMatchview umbenennen.

[EDIT]
Und so wie es aussieht suchst du im MatchHistoryViewModel nach dem _myMatchview . _myMatchview ist aber selbst das MatchHistoryViewModel. Da müsstest du das Binding für das Window auch noch anpassen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Urza am .
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”

- Patrick to Spongebob
private Nachricht | Beiträge des Benutzers
Papst
myCSharp.de - Experte



Dabei seit:
Beiträge: 350
Herkunft: Kassel

beantworten | zitieren | melden

Ein Binding muss bei WPF immer auf eine Property gehen, niemals auf eine Member Variable.

Wenn trotzdem noch nichts angezeigt wird, benötigst du INotifyPropertyChanged in deinem ViewModel, wenn du Veränderungen im Code an der gebundenen Collection machen willst, sollte es eine ObservableCollection sein.
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5960
Herkunft: Leipzig

beantworten | zitieren | melden

Hier gibt es eine ausführliche Einführung in MVVM mit Code-Beispielen: [Artikel] MVVM und DataBinding
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
Sindelfinger
myCSharp.de - Member



Dabei seit:
Beiträge: 22
Herkunft: Deutschland

Themenstarter:

beantworten | zitieren | melden

Zitat
Wenn trotzdem noch nichts angezeigt wird, benötigst du INotifyPropertyChanged in deinem ViewModel, wenn du Veränderungen im Code an der gebundenen Collection machen willst, sollte es eine ObservableCollection sein.

 
public class MatchHistoryViewModel : ViewModelBase
    { 
        public ObservableCollection<MatchViewModel> MatchHistory { get; }
        public MatchHistoryViewModel()
        {
            MatchHistory = new ObservableCollection<MatchViewModel>();
        }
        public void AddEntry(MatchViewModel i)
        {
     
            MatchHistory.Add(i);
        }    
    }

So hab ich es ja auch gemacht. Auch ein PropertyChangedEventhandler ist vorhanden, der im MatchviewModel auch brav gefeuert wird.
Zitat von Urza
Da müsstest du das Binding für das Window auch noch anpassen.
Sehr gerne - aber wie?
<Window x:Class="ListViewBinding.MainWindow"   
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MatchHistoryViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <DataGrid x:Name="Match" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding MatchHistory}" AutoGenerateColumns="True" Margin="-23,0,22.8,0" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Width="50" Binding="{Binding ID}"/>
                <DataGridTextColumn Header="Game" Width="150" Binding="{Binding GameName}"/>
                <DataGridTextColumn Header="Sets" Width="100" Binding="{Binding Sets2Play}"/>
                <DataGridTextColumn Header="Played" Width="100" Binding="{Binding SetsPlayed}"/>
            </DataGrid.Columns>
        </DataGrid>   
    </Grid>
    
</Window>



So, und nun zeigt's was an. Ich habe in mein Modul "Test2" einfach am Ende eingefügt

Match.DataContext = MyMatchView
. Jetzt zeigt mir das DGV mit Ausnahme der ID alles an, und wenn ich Einträge editiere, werden auch brav die Ereignisse gefeuert.

Erstmal herzlichen Dank für die Antworten. Hat wer eine Idee, warum die ID nicht angezeigt wird?

Hier nochmal die MatchHistory - Klasse:


     public class MatchViewModel : ViewModelBase
    {

        private int _ID;
        private string _GameName;
        private int _Sets2Play;
        private int _SetsPlayed;
        private int _Score0;
        private int _Score1;
        private string _Player1;
        private string _Player2;

        public int ID
        {
            get { return _ID; }
            set
            {
                _ID = value;
                RaisePropertyChanged(nameof(ID));
            }
        }
        public string GameName
        {
            get { return _GameName; }
            set
            {
                _GameName = value;
                RaisePropertyChanged(nameof(GameName));
            }
        }
        public int Sets2Play
        {
            get { return _Sets2Play; }
            set
            {
                _Sets2Play = value;
                RaisePropertyChanged(nameof(_Sets2Play));
            }
        }
        public int SetsPlayed
        {
            get { return _SetsPlayed; }
            set
            {
                _SetsPlayed = value;
                RaisePropertyChanged(nameof(SetsPlayed));
            }
        }
        public int Score0
        {
            get { return _Score0; }
            set
            {
                _Score0 = value;
                RaisePropertyChanged(nameof(Score0));
            }
        }
        public int Score1
        {
            get { return _Score1; }
            set
            {
                _Score1 = value;
                RaisePropertyChanged(nameof(Score1));
            }
        }
        public string Player1
        {
            get { return _Player1; }
            set
            {
                _Player1 = value;
                RaisePropertyChanged(nameof(Player1));
            }
        }
        public string Player2
        {
            get { return _Player2; }
            set
            {
                _Player2 = value;
                RaisePropertyChanged(nameof(Player2));
            }
        }
        
    }
    public class MatchHistoryViewModel : ViewModelBase
    { 
        public ObservableCollection<MatchViewModel> MatchHistory { get; }
        public MatchHistoryViewModel()
        {
            MatchHistory = new ObservableCollection<MatchViewModel>();
        }
        public void AddEntry(MatchViewModel i)
        {
     
            MatchHistory.Add(i);
        }    
    }
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            // Führt das Event aus und gibt den Property-Namen als Argument mit, damit WPF reagieren kann.
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

[EDIT] Auch das hat sich erledigt. Es hat sich eine negative Margin eingeschlichen (-46). Das ganze auf Null und fertig war's [/EDIT]
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sindelfinger am .
2 stupid 4 chess? No way.
2 stupid 4 C#? It seems so X(
private Nachricht | Beiträge des Benutzers
Sindelfinger
myCSharp.de - Member



Dabei seit:
Beiträge: 22
Herkunft: Deutschland

Themenstarter:

beantworten | zitieren | melden

Zitat von MrSparkle
Hier gibt es eine ausführliche Einführung in MVVM mit Code-Beispielen: [Artikel] MVVM und DataBinding

Herzlichen Dank. Diese Einführung habe ich mir im Vorfeld zu Gemüse geführt und - offensichtlich - nicht alles verstanden. Also arbeite ich das noch ein zweites mal durch.
2 stupid 4 chess? No way.
2 stupid 4 C#? It seems so X(
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5960
Herkunft: Leipzig

beantworten | zitieren | melden

Wenn es einen Bindingfehler gibt, steht der während der Ausführung im Ausgabefenster bzw. auch (in VS 2019) im Fenster für die WPF-Bindingfehler.

Ansonsten kannst du dir die Inhalte im Live Visual Tree anschauen bzw. mit einem DebugConverter. Siehe dazu den Abschnitt "Debugging" im MVVM-Artikel.
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
Sindelfinger
myCSharp.de - Member



Dabei seit:
Beiträge: 22
Herkunft: Deutschland

Themenstarter:

beantworten | zitieren | melden

Das wonach ich tagelang gesucht habe, habe ich hier im Forum gefunden. Herzlichen Dank an alle.

Und jetzt stoße ich auf dieses Video. Ein paar Tage zu spät.

Super erklärt anhand eines Beispiels.
2 stupid 4 chess? No way.
2 stupid 4 C#? It seems so X(
private Nachricht | Beiträge des Benutzers