En un proyecto WPF, tengo un control de usuario (Valve.xaml) que define una forma de polígono.

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

Estoy mostrando el control de usuario de Valve en un archivo xaml de ventana (FFG.xaml), como este:

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

Estoy configurando el DataContext de FFG.xaml a la clase FFG_ViewModel.cs, y contiene una instancia de la clase Valve_Model. Valve_Model representa esencialmente la válvula que se dibuja en la ventana en 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

}

Aquí está la clase 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

    }

PREGUNTA: Lo que quiero es que la propiedad Style en Valve.xaml cambie cuando cambie la propiedad IsValveOpen.

Entonces, si la válvula está abierta, entonces sería:

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

Y cuando la propiedad cambia a falsa, necesito que el estilo del polígono se cambie a:

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

¿Cómo hago para implementar esto exactamente?

0
Jagd 24 feb. 2017 a las 23:42

3 respuestas

La mejor respuesta

Podrías usar un IMultiValueConverter.

Primero, simplifiquemos el caso de uso. Básicamente, desea intercambiar Styles en función de un objeto de estado dado, que representaré con un ToggleButton. El hecho de que esté envolviendo todo en un UserControl tampoco tiene influencia en el concepto subyacente.

Demo:

  • Comenzando un nuevo proyecto
  • Declarando nuestro Resources
  • Alimentando el Window y el estado al 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();
    }
}

Cambiar a cualquier caso de uso específico significa:

  • Apuntando el enlace de la fuente familiar al Control que contiene el Resources (Estilos)
  • Usando el segundo enlace para agregar el estado a Converter (DP / INPC)
  • Implementando la lógica Converter
1
bab7lon 25 feb. 2017 a las 08:56

Puede (debería, por lo que sé) usar un DataTrigger, dentro de un ControlTemplate. Asumiendo que estos dos son tus estilos:

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

Debe agregar este estilo a los recursos:

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

Y úsalos en tus vistas:

 <Control DataContext="{Binding}" Style="{StaticResource changeStyle}" />
0
Ron 25 feb. 2017 a las 07:08

En lugar de establecer la propiedad real Style en un nuevo valor, puede agregar un DataTrigger al Estilo en sí que cambia las propiedades de Polygon en función del valor de {{X3} } propiedad de origen.

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>
0
mm8 26 feb. 2017 a las 12:03