Wpf 如何在用户控件中动态设置元素的样式

Wpf 如何在用户控件中动态设置元素的样式,wpf,binding,user-controls,Wpf,Binding,User Controls,在WPF项目中,我有一个定义多边形形状的用户控件(Valve.xaml) <Grid> <Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Style="{StaticResource Valve_Open}"/> </Grid> 以下是阀门型号等级: public class Valve_Model INotifyPropertyChanged { public event

在WPF项目中,我有一个定义多边形形状的用户控件(Valve.xaml)

<Grid>
   <Polygon Name="pValve" Points="0,50 0,20 50,50 50,20" Style="{StaticResource Valve_Open}"/>
</Grid>
以下是阀门型号等级:

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中的Style属性在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}"/>

我如何准确地实现这一点?

您可以(据我所知)在
控制模板中使用
DataTrigger
。假设这两种是您的风格:

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

您应该将此样式添加到资源中:

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

并在视图中使用它们:

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

您可以使用
IMultiValueConverter

首先,让我们简化用例。基本上,您希望基于给定的状态对象交换
样式
,我将用
切换按钮
来表示。您将所有内容包装在
UserControl
中,这一事实对底层概念也没有影响

演示:

  • 启动新项目
  • 声明我们的
    资源
  • 窗口
    和状态馈送至
    转换器
main window.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>
更改到任何特定用例意味着:

  • 将相对资源绑定指向保存
    资源(样式)的
    控件
  • 使用第二个绑定将状态添加到转换器(DP/INPC)
  • 实现
    转换器
    逻辑

您可以向样式本身添加一个
DataTrigger
,以根据
isvalvepen
源属性的值更改
多边形的属性,而不是将实际的
样式设置为新值

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>
<Grid>
    <cl:Valve x:Name="valve201A" DataContext="{Binding Valve201A}" />
</Grid>

FFG.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>
<Grid>
    <cl:Valve x:Name="valve201A" DataContext="{Binding Valve201A}" />
</Grid>


虽然这对于简单的组合来说是一个巧妙的技巧,但它并没有提供扩展(代码隐藏)和封装(库)的可能性,正如人们从
用户控件所期望的那样。这就做到了。谢谢你的帮助!
<Grid>
    <cl:Valve x:Name="valve201A" DataContext="{Binding Valve201A}" />
</Grid>