tags:

views:

77

answers:

1

Control :

C# Code :

public partial class RedGreenStatusIndicator : UserControl, INotifyPropertyChanged
    {
        public RedGreenStatusIndicator()
        {
            this.InitializeComponent();

            DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty
                (ArchiverDetails.ArDetailsProperty,
                typeof(ArchiverDetails));

            dpd.AddValueChanged(this, delegate { this.ObjectValueChanged(); });
            Status = false;
        }

        void RedGreenStatusIndicator_Loaded(object sender, RoutedEventArgs e)
        {

        }

        public bool Status
        {
            get { return (bool)GetValue(StatusProperty); }
            set 
            {
                bool old_value = Status;

                SetValue(StatusProperty, value);

                if ((old_value == true) && (Status == false))
                {
                    hide_green();
                    show_red();
                }

                if((old_value == false) && (Status == true))
                {
                    hide_red();
                    show_green();
                }
            }
        }

        private void show_green()
        {
            if (GreenInterior.Opacity == 0)
                run_storyboard("show_green_indicator");
        }

        private void hide_green()
        {
            if (GreenInterior.Opacity != 0)
                run_storyboard("hide_green_indicator");
        }

        private void show_red()
        {
            if (RedInterior.Opacity == 0)
                run_storyboard("show_red_indicator");
        }

        private void hide_red()
        {
            if (RedInterior.Opacity != 0)
                run_storyboard("hide_red_indicator");
        }

        private void run_storyboard(string resource_name)
        {
            Storyboard sb = (Storyboard)FindResource(resource_name);
            sb.Begin();
        }

        public static readonly DependencyProperty StatusProperty =
            DependencyProperty.Register("Status",
            typeof(bool),
            typeof(RedGreenStatusIndicator),
            new PropertyMetadata(null));

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void ObjectValueChanged()
        {



            OnPropertyChanged("Status");
        }

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

XAML :

<UserControl
    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"
    mc:Ignorable="d"
    x:Class="Manager.RedGreenStatusIndicator"
    x:Name="UserControl"
    d:DesignWidth="640" d:DesignHeight="480">
    <UserControl.Resources>
        <Storyboard x:Key="show_green_indicator">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="GreenInterior" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="hide_green_indicator">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="GreenInterior" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="show_red_indicator">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="RedInterior" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="hide_red_indicator">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="RedInterior" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>
    <Border BorderBrush="{DynamicResource SPDC_GRAY}" Background="{DynamicResource SPDC_BLACK}" CornerRadius="5,5,5,5" BorderThickness="1,1,1,1">
        <Grid Margin="2,2,2,2">
            <Grid.RowDefinitions>
                <RowDefinition Height="0.5*"/>
                <RowDefinition Height="0.5*"/>
            </Grid.RowDefinitions>
            <Border HorizontalAlignment="Stretch" x:Name="RedInterior" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Grid.RowSpan="2" Background="#FFF21818" Opacity="0"/>
            <Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Grid.RowSpan="2" x:Name="GreenInterior" Background="#FF1DD286" Opacity="0"/>
            <Border Margin="0,0,0,0" x:Name="Reflection" CornerRadius="5,5,0,0">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#99FFFFFF" Offset="0"/>
                        <GradientStop Color="#33FFFFFF" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>
            </Border>
        </Grid>
    </Border>
</UserControl>

Ok, So here's my control. Basically I intended it to have a public dependency property of type bool, which I could databind-to (hopefully). I've decided to see if it works and I've placed it in my project along with a checkbox, I then used databinding (working in Blend) to bind Status to Checkbox's IsChecked property. I was expecting to have the checkbox toggle the control's color.

The binding looks like this :

<RedGreenStatusIndicator HorizontalAlignment="Left" Margin="100,146,0,0" VerticalAlignment="Top" Width="64" Height="64" Status="{Binding Path=IsChecked, ElementName=checkBox, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="m_indicator"/>
        <CheckBox Margin="212,168,315,0" VerticalAlignment="Top" Height="24" Content="Click Me!" Style="{DynamicResource GlassCheckBox}" Foreground="{DynamicResource SPDC_WHITE}" x:Name="checkBox"/>

Also, In the Window's .Loaded I'm doing :

m_indicator.DataContext = this;

Here are my questions :

What on earth have I done wrong? Will I be able to use this in a ListViewItem template ? The listview is going to be databound to an observable_collection of objects which contain a bool property (which I'm hoping to bind to.

What do I need to do to make it work?

+2  A: 

Try keeping the codebehind as small as possible.
And especially: Do not put anything into a dependency-property "access-property's" setter - this code is not executed when the WPF changes the value.

Try this one:
Code-Behind:

public partial class StatusIndicator 
    : UserControl
{
    public static readonly DependencyProperty IsGreenProperty = DependencyProperty.Register("IsGreen", typeof(bool), typeof(StatusIndicator), new UIPropertyMetadata(false));

    public bool IsGreen
    {
        get
        {
            return (bool) GetValue(IsGreenProperty);
        }
        set
        {
            SetValue(IsGreenProperty, value);
        }
    }


    public StatusIndicator()
    {
        InitializeComponent();
    }
}

XAML:

<UserControl x:Class="WpfApplication1.StatusIndicator"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfApplication1="clr-namespace:WpfApplication1"
    Height="300" Width="300" x:Name="this">
    <UserControl.Template>
        <ControlTemplate TargetType="{x:Type WpfApplication1:StatusIndicator}">
            <ControlTemplate.Triggers>
                <DataTrigger Binding="{Binding ElementName=this, Path=IsGreen}"
                             Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard FillBehavior="HoldEnd">
                                <DoubleAnimation Duration="0:0:0.500"
                                                 From="0"
                                                 To="1"
                                                 Storyboard.TargetName="green"
                                                 Storyboard.TargetProperty="Opacity" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>

                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:0.500"
                                                 From="1"
                                                 To="0"
                                                 Storyboard.TargetName="green"
                                                 Storyboard.TargetProperty="Opacity" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </ControlTemplate.Triggers>

            <Grid>
                <Rectangle x:Name="red"
                           Fill="Red"/>
                <Rectangle x:Name="green"
                           Fill="Green" 
                           Opacity="0" />
            </Grid>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>
winSharp93
+1 for the advice on leaving logic out the property setter
IanR