2010-01-14 131 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