2010-01-14 128 views
1

控制(C#代码):自定义指标控制

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> 

好吧,是我的控制。基本上我打算它有一个类型为bool的公共依赖属性,我可以将它绑定到(希望)。我决定查看它是否可以工作,并且我已经将它与复选框一起放入我的项目中,然后使用数据绑定(在Blend中工作)将状态绑定到复选框的IsChecked属性。我期望有复选框切换控件的颜色。

的结合看起来是这样的:

<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"/> 

此外,在窗口的.Loaded我做:

m_indicator.DataContext = this; 

这里是我的问题:

究竟有我做错了? 我可以在ListViewItem模板中使用它吗?列表视图将被数据绑定到包含一个bool属性对象(我希望绑定到的observable_collection。

什么我需要做的,使工作?

回答

4

尽量保持代码隐藏尽可能小
,尤其是:不要将任何东西放入一个依赖属性“访问属性的”二传手 - 当WPF改变值不执行该代码

试试这个:
代码 - 背后:

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> 
+0

+1用于在离开逻辑从属性setter的建议 – kiwipom 2010-01-14 20:42:43