none
Auf RowState in DataGrid zugreifen RRS feed

  • Frage

  • Hallo!

    Ich möchte auf die RowState-Eigenschaft einer DataTable die ich als ItemsSource einem DataGrid zugewiesen habe in einem DataTrigger zugreifen:

    DataGrid Row Style:

    <Style TargetType="DataGridRow" x:Key="DG_RowState">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=Row.RowState, Mode=OneWay}" Value="Modified">
                <Setter Property="Background" Value="Yellow"/>
            </DataTrigger>
            </Style.Triggers>
    </Style>

    Verwendung Im DataGrid:

    <DataGrid Name="dgODBC" ... ItemsSource="{Binding}"   RowStyle="{StaticResource DG_RowState}" >

    Zuordnung der Daten in der CodeBehind:

    private void wndODBC_Loaded(object sender, RoutedEventArgs e)
    {
        tabODBC = (DS_ODBC.tabODBCDataTable)ar_Global.ar_XML.XMLtoDT(tabODBC, zNameKonfODBC, "ODBC-Konfigurations");     // Tabelle aus (XML) Konfigurationsdatei laden
        tabODBC.AcceptChanges();                                                    // Status aller Zeilen auf Grundzustand setzen
        dgODBC.ItemsSource = tabODBC;                                               // Dem DataGrid die Daten zur Verfügung stellen In der Tabelle (DataGrid) die eingelesene Konfiguration anzeigen
        dgODBC.DataContext = tabODBC;
    
    }

    Wenn ich mir den Status der DataGrid-Row (DataTabel-Row) anzeigen lasse, wird dieser immer korrekt angezeigt:

    if (dgODBC.SelectedItem != null)                                        // Ist eine Zeile ausgewählt?
    {
        DS_ODBC.tabODBCRow rowGB = (DS_ODBC.tabODBCRow)((System.Data.DataRowView)(dgODBC.SelectedItem)).Row;  // Akt. ausgewählte Zeile
        MessageBox.Show(rowGB.RowState.ToString());                         // Status der DataRow anzeigen
    ...

    Bei einer Änderung des DataRow-Status reagiert der Trigger jedoch nicht. Woran könnte das liegen??

    Hinweis:

    1. Bei neuen DataTable-Zeilen reagiert der Trigger ordnungsgemäß:

    <DataTrigger Binding="{Binding Row.RowState}" Value="Added">
        <Setter Property="Background" Value="Blue"/>
    </DataTrigger>


    2. Bei Bindings an Spalten der DataTable funktioniert der Trigger ebenfalls ordnungsgemäß:
    <DataTrigger Binding="{Binding AUSWAHL}" Value="true">
        <Setter Property="Foreground" Value="Black"/>
        <Setter Property="Background" Value="LightGreen"/>
    </DataTrigger>
    



    • Bearbeitet perlfred Donnerstag, 31. Juli 2014 07:24 Hinweis
    Mittwoch, 30. Juli 2014 07:58

Antworten

  • Hallo perlfred,

    >> Woran könnte das liegen??

    Das liegt ganz einfach daran, dass die RowState-Eigenschaft das Data Binding und somit Deinen Data Trigger nicht informiert, dass sie sich geändert hat.

    Eine solche Information geschieht im WPF/XAML-Umfeld über das PropertyChanged-Event, das im Interface INotifyPropertyChanged implementiert ist. Die DataRow bzw. die DataRowView implementiert dieses Interface jedoch nicht, somit hat der DataTrigger eigentlich keine Ahnung.

    Bei einer neuen Row funktioniert es auch nur, weil die neue Row von Anfang an diesen Added-Zustand hat. Wenn Du AcceptChanges() aufrufst wirst Du merken, dass sich auch hier der Zustand nicht ändern wird.

    >> Was wäre eine Lösung

    Weg von der DataTable und eigene Klassen bauen, die INotifyPropertyChanged implementieren und dann die entsprechenden Properties haben, die Du im Trigger nutzen kannst.

    >> Was wäre eine Lösung mit DataTable?

    Subklassen von DataTable und DataRow erstellen, so dass Du bei einer Änderung der Row das PropertyChanged-Event für die RowState-Property auslösen kannst. Hier ein funktionierendes Beispiel:

    <Window x:Class="WpfApplication2.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:WpfApplication2"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
      <Window.Resources>
        <Style TargetType="DataGridRow">
          <Style.Triggers>
            <DataTrigger Binding="{Binding Path=Row.RowState, Mode=OneWay}" Value="Modified">
              <Setter Property="Background" Value="Yellow"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Row.RowState}" Value="Added">
              <Setter Property="Background" Value="Blue"/>
            </DataTrigger>
          </Style.Triggers>
        </Style>
      </Window.Resources>
      <DataGrid x:Name="dataGrid" ItemsSource="{Binding}"/>
    </Window>

    Und Codebehind:

    using System;
    using System.ComponentModel;
    using System.Data;
    using System.Windows;
    using System.Windows.Shapes;
    
    namespace WpfApplication2
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
    
          this.Loaded += MainWindow_Loaded;
        }
    
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
          var table = new CustomDataTable();
          table.Columns.Add("FirstName", typeof(string));
          table.Columns.Add("LastName", typeof(string));
          var row = table.NewRow();
          row["FirstName"] = "Thomas";
          row["LastName"] = "Huber";
          table.Rows.Add(row);
          table.AcceptChanges();
          dataGrid.DataContext = table;
        }
        
      }
      public class CustomDataTable : DataTable
      {
        protected override Type GetRowType()
        {
          return typeof(CustomDataRow);
        }
        protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
        {
          return new CustomDataRow(builder);
        }
    
        protected override void OnRowChanged(DataRowChangeEventArgs e)
        {
          var customRow = e.Row as CustomDataRow;
          if(customRow!= null)
          {
            customRow.RaisePropertyChanged("RowState");
          }
        }
      }
      public class CustomDataRow : DataRow,INotifyPropertyChanged
      {
        public CustomDataRow(DataRowBuilder builder) : base(builder)
        {
        
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        internal void RaisePropertyChanged(string propertyName)
        {
          var handler = PropertyChanged;
          if(handler!= null)
          {
            handler(this, new PropertyChangedEventArgs(propertyName));
          }
        }
      }
    }


    Thomas Claudius Huber

    "If you can't make your app run faster, make it at least look & feel extremly fast"

    My latest Pluralsight-courses:
    XAML Layout in Depth
    Windows Store Apps - Data Binding in Depth

    twitter: @thomasclaudiush
    homepage: www.thomasclaudiushuber.com


    Mittwoch, 19. August 2015 21:29