Answered DataTrigger to an enum value (within a class)

  • Thursday, December 17, 2009 2:20 PM
     
     
    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 assassin316 Thursday, December 17, 2009 2:21 PM Readability
    • Edited by assassin316 Thursday, December 17, 2009 2:24 PM Changed question...
    •  

All Replies

  • Friday, December 18, 2009 3:30 PM
     
     
    Still haven't figured it out...
  • Friday, December 18, 2009 8:19 PM
     
      Has Code
    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
  • Tuesday, December 22, 2009 3:02 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 9:24 PM
     
      Has Code
    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
    •  
  • Wednesday, December 23, 2009 2:22 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 3:24 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 4:30 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 5:33 PM
     
     Answered Has Code
    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 assassin316 Wednesday, December 23, 2009 8:06 PM
    •  
  • Wednesday, December 23, 2009 8:06 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!