0
votes

WPF & XAML newbie here, so it's likely I have a totally wrong concept of how Triggers work...

Based on this question, I got my Trigger to work, but it runs only once on initial display of the screen, and takes whatever the initial value of the property is. If the property later changes (which can occur only when that screen is closed), when I re-open that screen, the Trigger behaves as if the property hadn't changed (i.e. it uses the property's original value).

What may be complicating the issue (maybe?) is that the class that defines the Trigger's DependencyProperty is a singleton. It was a singleton before I ever touched the code; I just added the DependencyProperty so I could add a Style Trigger in the XAML code to get different behavior depending on the selected report type. In the C# class property getter/setter I had to add the ".Instance" to access GetValue() and SetValue(), since the class is a singleton and I made the C# property a static. Not sure if that would mess up the DependencyProperty scheme, but I know that there's only one ReportSettingsData object being created because the Exception in the constructor is never thrown.

Here's a portion of the singleton class:

namespace MyApplication
{
   public enum SelectedReportType
   {
      EquipSummary,
      EventSummary,
      UserSummary,
      DiagSummary
   }

   public sealed class ReportSettingsData : DependencyObject
   {
      private static ReportSettingsData _instance; // singleton

      static ReportSettingsData() { new ReportSettingsData(); }

      private ReportSettingsData() // private because it's a singleton
      {
         // This is a singleton; the constructor should be called only once. Set _instance here so that
         // it's available immediately in case the constructor needs to access any DependencyProperty's.
         if (_instance != null)
            throw new Exception("ReportSettingsData ctor was called twice.");
         _instance = this;
         // ...other unrelated constructor code...
      }

      public static ReportSettingsData Instance
      {
         get { return _instance; }
      }

      public static SelectedReportType SelectedReport
      {
         get { return (SelectedReportType)Instance.GetValue(SelectedReportProperty); }
         set { Instance.SetValue(SelectedReportProperty, value); }
      }

      public static readonly DependencyProperty SelectedReportProperty =
         DependencyProperty.Register("SelectedReport", typeof(SelectedReportType),
                     typeof(ReportSettingsData)

                     // Set the default state of the 'SelectedReport' property
                     new PropertyMetadata(SelectedReportType.DiagSummary));

); } }

And the XAML for the reports page:

<my:HeaderVisual x:Class="MyApplication.ReportsView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:my="clr-namespace:MyApplication">

   <DataGrid Name="_dgReport"
                ColumnWidth="Auto"
                CanUserAddRows="False"
                VerticalScrollBarVisibility="Auto"
                HorizontalScrollBarVisibility="Auto"
                ItemsSource="{Binding}"
                IsReadOnly="True">
      <DataGrid.Resources>
         <Style TargetType="DataGridCell">


            <!-- Default setters for ALL report types... -->
            <Setter Property="TextBlock.Foreground" Value="HotPink"></Setter>


            <!-- But override some settings for Diagnostics reports... -->
            <Style.Triggers>
               <Trigger Property="my:ReportSettingsData.SelectedReport"  Value="{x:Static my:SelectedReportType.DiagSummary}">
                  <Setter Property="TextBlock.Foreground" Value="Goldenrod"></Setter>
               </Trigger>
            </Style.Triggers>


         </Style>
      </DataGrid.Resources>
   </DataGrid>

</my:HeaderVisual>

The default value of the SelectedReport property is set in the last line of the C# code above. If I set the default to DiagSummary, the Trigger in the XAML code fires and I get Goldenrod text for all four report types, regardless of the actual value of the SelectedReport property at the point I display the report screen. However, if I change the default to EquipSummary (or any other report type), that gives me HotPink text for all four report types. How can I get the Style Trigger & Setter to re-run if the SelectedReport property changes?

1
I dont understand why your model needs to be a DependencyObject just implement INotifyPropertyChanged in your model and have a cleaner way to debug. - Benedikt Schroeder
You don't need Dependency Property, you can use NotifyPropertyChanged as @BenediktSchroeder mentioned. If you wish to change the background color of your textbox (i.e. Datagridcell) you can create a value converter that accepts ReportType for that Record and return the color you want to set depending on the reprot type - D_Learning
@BenediktSchroeder: I'm really not even sure what you mean by "your model". What in my example is a "model"? Can you show me both the C# and XAML side of what you're talking about? - phonetagger
@D_Learning: Can you show me an example of both the C# and XAML side of what you're talking about? I've tried reading various sources on SO and other websites, but nearly everyone's example shows you the XAML side & assumes you're a C# expert & know everything about Dependency Properties so all they have to do is mention a few words about the C# side. I know neither side and would greatly appreciate a complete example that shows both sides. - phonetagger

1 Answers

0
votes

Try updating your existing code as below:

        <DataTrigger Binding="{Binding my:ReportSettingsData.SelectedReport}" Value="{x:Static my:SelectedReportType.DiagSummary}">
            <Setter Property="TextBlock.Foreground" Value="{StaticResource BgBrush1}" />
        </DataTrigger>

Also what are you binding to the DataGrid Item Source please let me know.