2017-02-24 84 views
0

在WPF項目,我具有限定一個多邊形形狀的用戶控件(Valve.xaml)。如何動態地設置的元件的樣式在一用戶控制

<Grid> 
    <Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Style="{StaticResource Valve_Open}"/> 
</Grid> 

我顯示在一個窗口XAML(FFG.xaml)文件中的閥門的用戶控制,像這樣:

<Window 
    <!-- removed other namespaces for brevity --> 
    xmlns:cl="clr-namespace:FFG.Controls;assembly=PID.Controls"> 
    <Grid> 
     <cl:Valve x:Name="valve201A"></cl:Valve> 
    </Grid> 
</Window> 

我設置FFG.xaml的DataContext的類FFG_ViewModel.cs,並且它包含Valve_Model類的一個實例。 Valve_Model基本上代表FFG.xaml窗口上繪製的閥門。

public class FFG_ViewModel : ViewModelBase { 

    public Valve_Model Valve201A { get; set; } 

    // There are other properties and methods, but I've removed them for brevity also 

} 

這裏是Valve_Model類:

public class Valve_Model INotifyPropertyChanged { 

     public event PropertyChangedEventHandler PropertyChanged; 

     private bool _isValveOpen { get; set; } 
     public bool IsValveOpen { 
      get { 
       return _isValveOpen; 
      } 
      set { 
       _isValveOpen = value; 
       OnPropertyChanged("IsValveOpen"); 
      } 
     } 

     #region INotifyPropertyChanged 
     protected virtual void OnPropertyChanged(string propertyName) { 
      PropertyChangedEventHandler handler = this.PropertyChanged; 
      if (handler != null) { 
       var e = new PropertyChangedEventArgs(propertyName); 
       handler(this, e); 
      } 
     } 
     #endregion 

    } 

問題: 我想是在Valve.xaml樣式屬性來更改IsValveOpen屬性發生變化時。

因此,如果閥門打開那麼這將是:

<Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Style="{StaticResource Valve_Open}"/> 

當屬性更改爲false,那麼我需要的多邊形的風格改爲:

<Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Style="{StaticResource Valve_Closed}"/> 

我該如何去實現這一點?

回答

1

你可以使用一個IMultiValueConverter

首先,讓我們簡單的使用情況。 Basicly您想根據給定的狀態對象,我會變成ToggleButton表示在交換Styles。那你在一個UserControl包裹一切的事實也對基本概念沒有影響。

演示:

  • 開始一個新項目
  • 聲明我們Resources
  • 養活Window和國家的Converter

MainWindow.xaml

<Window 

    ... 

    > 
    <Window.Resources> 
     <local:ToStyleConverter x:Key="ToStyleConverter"/> 
     <Style x:Key="Valve_Open" TargetType="{x:Type Polygon}"> 
      <Setter Property="Fill" Value="Red"/> 
     </Style> 
     <Style x:Key="Valve_Closed" TargetType="{x:Type Polygon}"> 
      <Setter Property="Fill" Value="Green"/> 
     </Style> 
    </Window.Resources> 
    <DockPanel> 
     <ToggleButton x:Name="butt" DockPanel.Dock="Bottom">Switch</ToggleButton> 
     <Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Stretch="Uniform"> 
      <Polygon.Style> 
       <MultiBinding Converter="{StaticResource ToStyleConverter}"> 
        <Binding RelativeSource="{RelativeSource FindAncestor, 
               AncestorType={x:Type Window}}"/> 
        <Binding ElementName="butt" Path="IsChecked"/> 
       </MultiBinding> 
      </Polygon.Style> 
     </Polygon> 
    </DockPanel> 
</Window> 

MainWindow.xaml。CS

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
} 

public class ToStyleConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, 
     object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (values[0] is Window) 
     { 
      Window win = (Window)values[0]; 
      if ((bool)values[1]) 
       return win.FindResource("Valve_Open"); 
      if (!(bool)values[1]) 
       return win.FindResource("Valve_Closed"); 
     } 
     return DependencyProperty.UnsetValue; 
    } 

    public object[] ConvertBack(object values, Type[] targetType, 
     object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

更改爲任何特定使用情況下,意味着:

  • 指向的RelativeSource結合到持有Resources(樣式)的Control
  • 使用第二結合到狀態添加到Converter(DP/INPC)
  • 實施Converter邏輯
+0

這樣做了。謝謝您的幫助! – Jagd

0

可以(應該像我知道)使用DataTrigger,一個ControlTemplate內。假設這兩個是你的風格:在你的看法

<Style x:Key="changeStyle" TargetType="Control"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="Control"> 
        <Grid> 
         <Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Style="{StaticResource Valve_Open}" /> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <DataTrigger Binding="{Binding Valve201A.IsValveOpen}" Value="true"> 
          <Setter TargetName="pValve" Property="Style" Value="{StaticResource Valve_Close}" /> 
         </DataTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

,並利用它們:

<Window.Resources> 
    <Style TargetType="Polygon" x:Key="Valve_Open"> 
     <Setter Property="Fill" Value="Red"/> 
    </Style> 
    <Style TargetType="Polygon" x:Key="Valve_Close"> 
     <Setter Property="Fill" Value="Green"/> 
    </Style> 
</Window.Resources> 

你應該這種風格添加到資源

<Control DataContext="{Binding}" Style="{StaticResource changeStyle}" /> 
+0

雖然這是簡單的組合物中的巧妙的方法,它提供了用於擴展無可能性(後面的代碼)和封裝(庫),正如人們期望從一個'UserControl'。 – bab7lon

0

而不是實際的Style屬性設置爲一個新值,您可以添加一個DataTrigger到改變Polygon的基礎上,IsValveOpen源屬性的值的屬性的樣式本身。

Valve.xaml:

<Grid> 
    <Polygon Name="pValve" Points="0,50 0,20 50,50 50,20"> 
     <Polygon.Style> 
      <Style TargetType="Polygon"> 
       <!-- Copy the setters from the Valve_Closed style here --> 
       <Setter Property="Fill" Value="Red" /> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding IsValveOpen}" Value="True"> 
         <!-- Copy the setters from the Valve_Open style here --> 
         <Setter Property="Fill" Value="Red" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Polygon.Style> 
    </Polygon> 
</Grid> 

FFG.xaml:

<Grid> 
    <cl:Valve x:Name="valve201A" DataContext="{Binding Valve201A}" /> 
</Grid> 
相關問題