none
Zeilen ohne Inhalt im DataGrid (WPF) RRS feed

  • Frage

  • Hallo Zusammen,

    Ich habe mich heute damit beschäftigt eine Tabelle in mein mainWindow einzupflegen. Dabei bin ich auf DataGrid gestoßen, welches man als Tabelle in einer WPF Anwendung verwenden kann. Nach einigen fehlgeschlagenen Versuchen eine Zeile zu generieren habe ich mich entschlossen es hier zu posten. Was mache ich falsch?

    Die Klasse AnzMesswerte wird in Projektnamespace definiert

        public class AnzMesswert
        {
            public string AnzeigeNummer { set; get; }
            public string Value { set; get; }
            public string Value2 { set; get; }
        }

    Anbei der Code für das Erstellen der Tabelle in XAML

                        <DataGrid Name="tblData" Margin="-1,-296,0,0" HorizontalAlignment="Left" Width="427" VerticalAlignment="Top" Height="157" FontSize="20" HorizontalContentAlignment="Center" AlternationCount="8" RowHeight="30" RowDetailsVisibilityMode="Visible">
                            <DataGrid.Columns>
                                <DataGridTextColumn Header="ghgtftzdf"/>
                                <DataGridTextColumn Header="sdf"/>
                                <DataGridTextColumn Header="sdf"/>
                            </DataGrid.Columns>
                            <local:AnzMesswert AnzeigeNummer="fgdsfgdfh" Value="dfhdh" Value2="55554"/>
                            <local:AnzMesswert AnzeigeNummer="4567" Value="35" Value2="54"/>
                            <local:AnzMesswert AnzeigeNummer="4567" Value="35" Value2="54"/>
                        </DataGrid>

    Ich bin am verzweifeln und hoffe ihr könnt mir helfen.

    Vielen Dank und Viele Grüße
    Martin

    Freitag, 6. April 2018 16:01

Antworten

  • Hi Martin,
    fang am besten einfach an. Erzeuge eine Liste mit Datenobjekten und binde diese Liste an ein DataGrid, z.B. so, wie in der folgenden Demo.

    XAML:

    <Window x:Class="WpfApp1CS.Window41"
            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:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window41" Height="300" Width="300">
      <Window.Resources>
        <local:Window41VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <DataGrid ItemsSource="{Binding View}"/>
      </Grid>
    </Window>

    Dazu der ViewModel mit der Datenklasse:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApp1CS
    {
      public class Window41VM
      {
        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View
        {
          get
          {
            if (cvs.Source == null) cvs.Source = GetData();
            return cvs.View;
          }
        }
    
        private ObservableCollection<AnzMesswert> GetData()
        {
          ObservableCollection<AnzMesswert> col = new ObservableCollection<AnzMesswert>();
          for (int i = 1; i < 10; i++)
            col.Add(new AnzMesswert() { AnzeigeNummer = i.ToString(), Value = i.ToString(), Value2 = i.ToString() });
          return col;
        }
        public class AnzMesswert
        {
          public string AnzeigeNummer { set; get; }
          public string Value { set; get; }
          public string Value2 { set; get; }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert mApO18 Sonntag, 8. April 2018 14:21
    Freitag, 6. April 2018 18:47
  • Hi Martin,
    den CodeBehind gleichzeitig als Ressource hinzufügen, die dann instanziiert wird, bringt Fehler, da der Contructor dann nochmals ausgeführt wird. Mache es so, wie ich es geschrieben hatte: ViewModel als separate Klasse. Dann funktioniert es. Hier mal eine Demo mit Deinen Ausschnitten:

    XAML:

    <Window x:Class="DXF.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:DXF"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="825">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
      </Window.Resources>
      <Grid Name="mainGrid" Focusable="True">
        <TabControl Margin="0,40,0,-26">
          <TabItem Header="General">
            <TabPanel VerticalAlignment="Top" HorizontalAlignment="Left" Height="370" Width="762">
              <TextBox x:Name="tbData" Height="296" VerticalAlignment="Top" HorizontalAlignment="Left" Width="282" BorderThickness="2"/>
              <Button x:Name="btnDisconnect" Content="Disconnect" Height="30" Margin="-222.333,0,0,-36" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="btnDisconnect_Click" Width="109" />
              <Button x:Name="btnRead" Content="Read Ascii" Margin="-350.333,0,401,34" RenderTransformOrigin="0.492,-0.084" Click="btnRead_Click" Height="30" VerticalAlignment="Bottom"/>
              <Button x:Name="btnConnect" Content="Connect" Height="30" Margin="21,6,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Click="btnConnect_Click" Width="100" RenderTransformOrigin="1.125,0.417"/>
              <TextBox Name="statusText" Text="Status: Initialisierung..." Margin="102.444,-29,-18.222,0" Height="29" VerticalAlignment="Top" RenderTransformOrigin="1.081,0.397" HorizontalAlignment="Left" Width="122" />
              <Grid DataContext="{StaticResource vm}" Margin="-67,-286,0,286" HorizontalAlignment="Right" Width="287">
                <DataGrid ItemsSource="{Binding View}">
                </DataGrid>
              </Grid>
            </TabPanel>
          </TabItem>
        </TabControl>
      </Grid>
    </Window>

    Und dazu der gesamte Code:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace DXF
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow() { InitializeComponent(); }
        private void btnDisconnect_Click(object sender, RoutedEventArgs e) { }
        private void btnRead_Click(object sender, RoutedEventArgs e) { }
        private void btnConnect_Click(object sender, RoutedEventArgs e) { }
      }
    
      public class ViewModel
      {
        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View
        {
          get
          {
            if (cvs.Source == null) cvs.Source = GetData();
            return cvs.View;
          }
        }
    
        private ObservableCollection<AnzMesswert> GetData()
        {
          ObservableCollection<AnzMesswert> col = new ObservableCollection<AnzMesswert>();
          for (int i = 1; i < 10; i++)
            col.Add(new AnzMesswert() { AnzeigeNummer = i.ToString(), Value = i.ToString(), Value2 = i.ToString() });
          return col;
        }
        public class AnzMesswert
        {
          public string AnzeigeNummer { set; get; }
          public string Value { set; get; }
          public string Value2 { set; get; }
        }
      }
    }
    


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 8. April 2018 09:42

Alle Antworten

  • Hi Martin,
    fang am besten einfach an. Erzeuge eine Liste mit Datenobjekten und binde diese Liste an ein DataGrid, z.B. so, wie in der folgenden Demo.

    XAML:

    <Window x:Class="WpfApp1CS.Window41"
            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:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window41" Height="300" Width="300">
      <Window.Resources>
        <local:Window41VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <DataGrid ItemsSource="{Binding View}"/>
      </Grid>
    </Window>

    Dazu der ViewModel mit der Datenklasse:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApp1CS
    {
      public class Window41VM
      {
        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View
        {
          get
          {
            if (cvs.Source == null) cvs.Source = GetData();
            return cvs.View;
          }
        }
    
        private ObservableCollection<AnzMesswert> GetData()
        {
          ObservableCollection<AnzMesswert> col = new ObservableCollection<AnzMesswert>();
          for (int i = 1; i < 10; i++)
            col.Add(new AnzMesswert() { AnzeigeNummer = i.ToString(), Value = i.ToString(), Value2 = i.ToString() });
          return col;
        }
        public class AnzMesswert
        {
          public string AnzeigeNummer { set; get; }
          public string Value { set; get; }
          public string Value2 { set; get; }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert mApO18 Sonntag, 8. April 2018 14:21
    Freitag, 6. April 2018 18:47
  • Hallo Peter,

    vielen Dank für deine Antwort. Das hätte ich nie so hinbekommen. Dein Beispiel funktioniert einwandfrei. Jetzt habe ich allerdings noch weitere Controls in meiner Anwendung, die nun nicht mehr über InitializeComponent() im MainWindow erstellt werden. Was macht dieses StaticResource vm?

     <Window.Resources>
        <local:Window41VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <DataGrid ItemsSource="{Binding View}"/>
      </Grid>

    Wenn ich die Zeile

    <local:Window41VM x:Key="vm"/>

    herausnehme, dann werden die Controls (buttons und textbox) in meiner xaml über InitializeComponent()  geladen, jedoch die Tabelle (datagrid) nicht mehr und umgekehrt.

                    <TabPanel VerticalAlignment="Top" HorizontalAlignment="Left" Height="370" Width="762">
                        <TextBox x:Name="tbData" Height="296" VerticalAlignment="Top" HorizontalAlignment="Left" Width="282" BorderThickness="2"/>
                        <Button x:Name="btnDisconnect" Content="Disconnect" Height="30" Margin="-222.333,0,0,-36" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="btnDisconnect_Click" Width="109" />
                        <Button x:Name="btnRead" Content="Read Ascii" Margin="-350.333,0,401,34" RenderTransformOrigin="0.492,-0.084" Click="btnRead_Click" Height="30" VerticalAlignment="Bottom"/>
                        <Button x:Name="btnConnect" Content="Connect" Height="30" Margin="21,6,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Click="btnConnect_Click" Width="100" RenderTransformOrigin="1.125,0.417"/>
                        <TextBox Name="statusText" Text="Status: Initialisierung..." Margin="102.444,-29,-18.222,0" Height="29" VerticalAlignment="Top" RenderTransformOrigin="1.081,0.397" HorizontalAlignment="Left" Width="122" />
    
                        <Grid DataContext="{StaticResource vm}" Margin="-67,-286,0,286" HorizontalAlignment="Right" Width="287">
                            <DataGrid ItemsSource="{Binding View}">
                            </DataGrid>
                        </Grid>

    Vielen Dank und viele Grüße

    Martin

    Samstag, 7. April 2018 08:52
  • Hi Martin,
    hast Du den CodeBehind zum MainWindow gelöscht? Wenn ja, dann wird auch kein InitializeComponent mehr aufgerufen und die mit dem Designer erzeugten Steuerelemente fehlen dann bzw. funktionieren nicht richtig (wegen fehlender Ereignishandler).

    Die Resource mit dem Schlüssel "vm" bei mir ist der ViewModel, der bei der ersten Nutzung instanziiert wird und dann für das Window zur Verfügung steht. Das passiert im Grid, wo der  DataContext auf die Resource gesetzt wird. Damit steht die ViewModel-Instanz im Grid und allen darin eingebetteten Steuerelementen als DataContext zur Verfügung. Im DataGrid werden dann die anzuzeigenden Daten aus der Eigenschaft "View" im DataContext resp. ViewModel geholt.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Samstag, 7. April 2018 09:07
  • Hi Peter,

    ich habe nichts gelöscht. Nur die Table anhand von deinem Beispiel eingepflegt. Nach dem Kompilieren von  InitializeComponent(); folgt System.StackOverflowException.

    Anbei nochmal der Quellcode:

            public MainWindow()
            {
                InitializeComponent();
                UserInitialization();
    
                // by default it will create an AutoCad2000 dxf version
                DxfDocument dxf = new DxfDocument();
            }
    

    XAML:

    <Window x:Class="DXF.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:DXF"   
            mc:Ignorable="d"
            Title="EasyControl" Height="450" Width="800">
        <Window.Resources>
            <local:MainWindow x:Key="vm"/>
        </Window.Resources>
        <Grid Name="mainGrid" Focusable="True">
            <TabControl Margin="0,40,0,-26">
                <TabItem Header="General">
                    <TabPanel VerticalAlignment="Top" HorizontalAlignment="Left" Height="370" Width="762">
                        <TextBox x:Name="tbData" Height="296" VerticalAlignment="Top" HorizontalAlignment="Left" Width="282" BorderThickness="2"/>
                        <Button x:Name="btnDisconnect" Content="Disconnect" Height="30" Margin="-222.333,0,0,-36" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="btnDisconnect_Click" Width="109" />
                        <Button x:Name="btnRead" Content="Read Ascii" Margin="-350.333,0,401,34" RenderTransformOrigin="0.492,-0.084" Click="btnRead_Click" Height="30" VerticalAlignment="Bottom"/>
                        <Button x:Name="btnConnect" Content="Connect" Height="30" Margin="21,6,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Click="btnConnect_Click" Width="100" RenderTransformOrigin="1.125,0.417"/>
                        <TextBox Name="statusText" Text="Status: Initialisierung..." Margin="102.444,-29,-18.222,0" Height="29" VerticalAlignment="Top" RenderTransformOrigin="1.081,0.397" HorizontalAlignment="Left" Width="122" />
                        <Grid DataContext="{StaticResource vm}" Margin="-67,-286,0,286" HorizontalAlignment="Right" Width="287">
                            <DataGrid ItemsSource="{Binding View}">
                            </DataGrid>
                        </Grid>
                    </TabPanel>
                </TabItem>

    Wie schon gesagt, die Buttons und Textboxes werden nicht initialisiert. An welcher Stelle liegt der Fehler?

    Viele Grüße
    Martin

    Samstag, 7. April 2018 21:56
  • Hi Martin,
    den CodeBehind gleichzeitig als Ressource hinzufügen, die dann instanziiert wird, bringt Fehler, da der Contructor dann nochmals ausgeführt wird. Mache es so, wie ich es geschrieben hatte: ViewModel als separate Klasse. Dann funktioniert es. Hier mal eine Demo mit Deinen Ausschnitten:

    XAML:

    <Window x:Class="DXF.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:DXF"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="825">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
      </Window.Resources>
      <Grid Name="mainGrid" Focusable="True">
        <TabControl Margin="0,40,0,-26">
          <TabItem Header="General">
            <TabPanel VerticalAlignment="Top" HorizontalAlignment="Left" Height="370" Width="762">
              <TextBox x:Name="tbData" Height="296" VerticalAlignment="Top" HorizontalAlignment="Left" Width="282" BorderThickness="2"/>
              <Button x:Name="btnDisconnect" Content="Disconnect" Height="30" Margin="-222.333,0,0,-36" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="btnDisconnect_Click" Width="109" />
              <Button x:Name="btnRead" Content="Read Ascii" Margin="-350.333,0,401,34" RenderTransformOrigin="0.492,-0.084" Click="btnRead_Click" Height="30" VerticalAlignment="Bottom"/>
              <Button x:Name="btnConnect" Content="Connect" Height="30" Margin="21,6,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Click="btnConnect_Click" Width="100" RenderTransformOrigin="1.125,0.417"/>
              <TextBox Name="statusText" Text="Status: Initialisierung..." Margin="102.444,-29,-18.222,0" Height="29" VerticalAlignment="Top" RenderTransformOrigin="1.081,0.397" HorizontalAlignment="Left" Width="122" />
              <Grid DataContext="{StaticResource vm}" Margin="-67,-286,0,286" HorizontalAlignment="Right" Width="287">
                <DataGrid ItemsSource="{Binding View}">
                </DataGrid>
              </Grid>
            </TabPanel>
          </TabItem>
        </TabControl>
      </Grid>
    </Window>

    Und dazu der gesamte Code:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace DXF
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow() { InitializeComponent(); }
        private void btnDisconnect_Click(object sender, RoutedEventArgs e) { }
        private void btnRead_Click(object sender, RoutedEventArgs e) { }
        private void btnConnect_Click(object sender, RoutedEventArgs e) { }
      }
    
      public class ViewModel
      {
        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View
        {
          get
          {
            if (cvs.Source == null) cvs.Source = GetData();
            return cvs.View;
          }
        }
    
        private ObservableCollection<AnzMesswert> GetData()
        {
          ObservableCollection<AnzMesswert> col = new ObservableCollection<AnzMesswert>();
          for (int i = 1; i < 10; i++)
            col.Add(new AnzMesswert() { AnzeigeNummer = i.ToString(), Value = i.ToString(), Value2 = i.ToString() });
          return col;
        }
        public class AnzMesswert
        {
          public string AnzeigeNummer { set; get; }
          public string Value { set; get; }
          public string Value2 { set; get; }
        }
      }
    }
    


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 8. April 2018 09:42
  • Perfekt, Danke!
    Sonntag, 8. April 2018 14:21