none
DataTrigger to an enum value (within a class)

    Question

  • I have successfully coded my first DataTigger to trigger based on an Enumeration, but my only dislike is that my enumeration is global to my namespace. I have the following:


    My global enum ...

    Public Enum eLEDStates
        Off
        Pending
        [On]
    End Enum


    My custom button's dependency property ...

    Public Property LEDState() As eLEDStates
            Get
                Return GetValue(LEDStateProperty)
            End Get
            Set(ByVal value As eLEDStates)
                SetValue(LEDStateProperty, value)
            End Set
    End Property


    My DataTrigger ...

    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=LEDState}">
         <DataTrigger.Value>
              <local:eLEDStates>On</local:eLEDStates>
         </DataTrigger.Value>
         <Setter TargetName="LED" Property="Fill" Value="{StaticResource LEDOnBrush}"/>
    </DataTrigger>



    My question is the following:

    If I move the enumeration to the CustomButton class instead of it being declared globally in the namespace, how do I change my DataTrigger to reflect the change ???

    Thank you !!
    • Edited by maximus37 Thursday, December 17, 2009 2:24 PM Changed question...
    Thursday, December 17, 2009 2:20 PM

Answers

  • Hello again

    Prettyman in his post is right, the same markup will work within a control template. If I understand correctly your target is a Border named 'LED' and your DataTrigger is trying to set its 'Fill' property which it does not have? Is this the source of the error?

    I have made a working example - replacing the Border with a Rectangle.

    <ControlTemplate TargetType="{x:Type local:LEDButton}">
    
        <Border>
    
            <StackPanel Orientation="Horizontal">
    
                <Rectangle Height="20" Width="20" x:Name="LED" />
    
                <TextBlock Text="LEDButton" />
    
            </StackPanel>
    
        </Border>
    
        <ControlTemplate.Triggers>
    
            <DataTrigger Binding="..." Value="{x:Static local:LEDButton+eLEDStates.Off}">
    
                <Setter Property="Fill" TargetName="LED" Value="Red" />
    
            </DataTrigger>
    
            <DataTrigger Binding="..." Value="{x:Static local:LEDButton+eLEDStates.Pending}">
    
                <Setter Property="Fill" TargetName="LED" Value="Green" />
    
            </DataTrigger>
    
            <DataTrigger Binding="..." Value="{x:Static local:LEDButton+eLEDStates.On}">
    
                <Setter Property="Fill" TargetName="LED" Value="Blue" />
    
            </DataTrigger>
            
        </ControlTemplate.Triggers>
    
    </ControlTemplate>
    And the code behind, sorry for the C#:


        public class LEDButton : Button
        {
            public enum eLEDStates
            {
                Off,
                Pending,
                On,
            };
    
            public eLEDStates LEDState
            {
                get { return (eLEDStates)this.GetValue(LEDButton.LEDStateProperty); } // end get
    
                set { this.SetValue(LEDButton.LEDStateProperty, value); } // end set
            }
    
            public readonly static DependencyProperty LEDStateProperty = DependencyProperty.Register(...);
        }
    Hope this solves the problem.
    • Edited by indiecs Wednesday, December 23, 2009 5:49 PM Readability
    • Marked as answer by maximus37 Wednesday, December 23, 2009 8:06 PM
    Wednesday, December 23, 2009 5:33 PM

All replies

  • Still haven't figured it out...
    Friday, December 18, 2009 3:30 PM
  • Hi there,

    I don't really know what you're after, but if you're trying to setup a three-state control, why not use a styled checkbox instead?

    Here's a little quickie:

    <Window x:Class="WpfTests.LEDCheckBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LEDCheckBox" Height="300" Width="300">
    
        <Window.Resources>
            <SolidColorBrush x:Key="OnBackgroundBrush" Color="Green"/>
            <SolidColorBrush x:Key="OffBackgroundBrush" Color="Red"/>
            <SolidColorBrush x:Key="PendingBackgroundBrush" Color="Gray"/>
    
            <SolidColorBrush x:Key="OnBorderBrush" Color="LightGreen"/>
            <SolidColorBrush x:Key="OffBorderBrush" Color="DarkRed"/>
            <SolidColorBrush x:Key="PendingBorderBrush" Color="DarkGray"/>
    
            <SolidColorBrush x:Key="HoverBorderBrush" Color="Orange"/>
    
            <Style x:Key="LEDCheckBox" TargetType="CheckBox">
                <Setter Property="SnapsToDevicePixels" Value="true"/>
                <Setter Property="OverridesDefaultStyle" Value="true"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="CheckBox">
                            <Border x:Name="Border" 
                                    Width="25" 
                                    Height="25" 
                                    CornerRadius="3" 
                                    BorderThickness="2">
                                <ContentPresenter Margin="2"
                                                  VerticalAlignment="Center"
                                                  HorizontalAlignment="Center"/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="true">
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource OnBackgroundBrush}"/>
                                    <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource OnBorderBrush}"/>
                                </Trigger>
                                <Trigger Property="IsChecked" Value="false">
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource OffBackgroundBrush}"/>
                                    <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource OffBorderBrush}"/>
                                </Trigger>
                                <Trigger Property="IsChecked" Value="{x:Null}">
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource PendingBackgroundBrush}"/>
                                    <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource PendingBorderBrush}"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource HoverBorderBrush}" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
    
    
        <StackPanel>
            <CheckBox Style="{StaticResource LEDCheckBox}"
                    IsChecked="{Binding ElementName=chk, Path=IsChecked}"
                    Margin="20"
                    />
            <!-- If users shouldn't be allowed to change state:
            <CheckBox Style="{StaticResource LEDCheckBox}"
                    IsChecked="{Binding ElementName=chk, Path=IsChecked}"
                    Margin="20"
                    IsHitTestVisible="False"
                    IsTabStop="False"
                    />
            -->
            <CheckBox x:Name="chk"
                    HorizontalAlignment="Center" 
                    IsThreeState="True"
                    Content="On/Off/Pending" 
                    Margin="20"
                    />
        </StackPanel>
    </Window>
    

    Cheers,
    Olaf
    Friday, December 18, 2009 8:19 PM
  • Thanks Olaf, but I can't do that. I need to use an Enum because I'm using the Enum in procedural code too.
    Tuesday, December 22, 2009 3:02 PM
  • Hello,

    Not sure why you want a nested enum but the following should work.

    I would think the enum would have to public within the class.

    Hope it helps.

     

    <DataTemplate DataType="{x:Type local:myCustomButton+eLEDStates}">  
    
       <DataTemplate.Triggers> 
    
          <DataTrigger Binding="..." Value="{x:Static local:myCustomButton+eLEDStates.On}"> 
    
             <Setter Property="..." TargetName="..." Value="..." />
    
          </DataTrigger>
    
       </DataTemplate.Triggers> 
    
    </DataTemplate>
    
    

     

    • Edited by indiecs Tuesday, December 22, 2009 9:31 PM Readability
    Tuesday, December 22, 2009 9:24 PM
  • Thanks for the reply indiecs!

    I cannot use a DataTemplate for my problem because my DataTriggers exist within a ControlTemplate, and my target is a child element of the ControlTemplate (my target element is a Border with the name "LED"). Therefore, when I set the TargetName, it does not recognize my "LED" element.

    I want to nest my Enum within my class because the Enum is only specific to my Custom Button class, therefore having it public is a little more messy than having it exist within the Custom Button class.


    Wednesday, December 23, 2009 2:22 PM
  • Hi there,

    I still don't really see the need to create a custom control for this, even if you want to use an enum for setting/retrieving the control's state - you could define your enum somewhere plus a method that would "translate" it into IsChecked and one for retrieving its value. Or you could pack everything into a UserControl and use that.

    But whatever,  do you have some copy'n'paste-ready example of your control and a window that uses it? If so, please post it.
    Cheers,
    Olaf
    Wednesday, December 23, 2009 3:24 PM
  • Hey Assassin...  I'm not 100% here but I'm pretty sure that the same markup for binding (ie DataTriggers and the local:mycustombutton+eLEDStates.On ) would be the same in your control template, there would be some minor changes but try the <DataTrigger> section, I think it'll do the trick.
    Wednesday, December 23, 2009 4:30 PM
  • Hello again

    Prettyman in his post is right, the same markup will work within a control template. If I understand correctly your target is a Border named 'LED' and your DataTrigger is trying to set its 'Fill' property which it does not have? Is this the source of the error?

    I have made a working example - replacing the Border with a Rectangle.

    <ControlTemplate TargetType="{x:Type local:LEDButton}">
    
        <Border>
    
            <StackPanel Orientation="Horizontal">
    
                <Rectangle Height="20" Width="20" x:Name="LED" />
    
                <TextBlock Text="LEDButton" />
    
            </StackPanel>
    
        </Border>
    
        <ControlTemplate.Triggers>
    
            <DataTrigger Binding="..." Value="{x:Static local:LEDButton+eLEDStates.Off}">
    
                <Setter Property="Fill" TargetName="LED" Value="Red" />
    
            </DataTrigger>
    
            <DataTrigger Binding="..." Value="{x:Static local:LEDButton+eLEDStates.Pending}">
    
                <Setter Property="Fill" TargetName="LED" Value="Green" />
    
            </DataTrigger>
    
            <DataTrigger Binding="..." Value="{x:Static local:LEDButton+eLEDStates.On}">
    
                <Setter Property="Fill" TargetName="LED" Value="Blue" />
    
            </DataTrigger>
            
        </ControlTemplate.Triggers>
    
    </ControlTemplate>
    And the code behind, sorry for the C#:


        public class LEDButton : Button
        {
            public enum eLEDStates
            {
                Off,
                Pending,
                On,
            };
    
            public eLEDStates LEDState
            {
                get { return (eLEDStates)this.GetValue(LEDButton.LEDStateProperty); } // end get
    
                set { this.SetValue(LEDButton.LEDStateProperty, value); } // end set
            }
    
            public readonly static DependencyProperty LEDStateProperty = DependencyProperty.Register(...);
        }
    Hope this solves the problem.
    • Edited by indiecs Wednesday, December 23, 2009 5:49 PM Readability
    • Marked as answer by maximus37 Wednesday, December 23, 2009 8:06 PM
    Wednesday, December 23, 2009 5:33 PM
  • YES!!  It works like a charm  :)

    Thank you very much indiecs!!  Everyday I learn more and more about WPF, and thanks to people like you, I also learn a lot through the problems/solutions I encounter.

    Have a great day!

    Wednesday, December 23, 2009 8:06 PM