0

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?

Community
  • 1
  • 1
phonetagger
  • 7,701
  • 3
  • 31
  • 55
  • 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 Jul 29 '15 at 14:38
  • 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 Jul 29 '15 at 14:54
  • @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 Jul 29 '15 at 15:16
  • @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 Jul 29 '15 at 15:20

1 Answers1

0

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.

D_Learning
  • 1,033
  • 8
  • 18
  • As far as the XAML code snippet goes, I replaced my ` ... ` with the code you provided. Visual Studio gives me the error "The resource 'BgBrush1' could not be resolved." How should I define BgBrush1? I tried replacing that with `Value="Goldenrod"` and it compiled, but my text was HotPink regardless of what report was selected, so it seems like perhaps the `DataTrigger` is not dynamically triggering? – phonetagger Jul 29 '15 at 19:50
  • You asked what I'm binding the DataGrid ItemSource to... I assume you're referring to `ItemsSource="{Binding}"`? This is not my code, and I'm not all that familiar with WPF/XAML in the first place, but it appears that in the code-behind file ReportsView.xaml.cs, the constructor for ReportsView is doing the following (slightly different for each report type): `_dgReport.ItemsSource = new ObservableCollection(_report.Cast());` – phonetagger Jul 29 '15 at 19:56
  • What is _report? I assume it might be Enumerable, just need to know what excatly is ti returning... Also what do you excatly want to show on your datagrid. Its confusing because as per your Question it seems you want to show your Enum values on your Grid. – D_Learning Jul 29 '15 at 20:13
  • The enum is just an enumeration of the four different types of reports (equipment status history, event history, user login history, or diagnostics history). Depending on which one is selected, a different set of data is shown; different number of columns, different information, whatever. The settings for the DataGrid need to be different for the diagnostics report. I'm using `Foreground` as a sample difference (the real differences are TextBlock.TextAlignment, TextBlock.TextWrapping, and a couple others). By using `Foreground` colors HotPink and Goldenrod it's easy to see if it worked. – phonetagger Jul 29 '15 at 20:21
  • `public abstract class ReportLine { public abstract XDocument ToXml(); }` and `private ObservableCollection _report;` – phonetagger Jul 29 '15 at 20:24