Используйте StyleSelector для кнопки

У меня есть требование изменить стиль кнопки на основе значения в данных. Похоже, что StyleSelector будет работать отлично, но, похоже, не существует способа установить его для кнопки.

Есть ли способ динамически установить стиль кнопки из данных? Может быть, даже чистый подход XAML?

Ответ 1

Вы можете разместить стили Button в словаре ресурсов и привязать стиль для Button и использовать конвертер

ButtonStyles.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="ButtonStyle1" TargetType="Button">
        <Setter Property="Background" Value="Green"/>
        <Setter Property="FontSize" Value="12"/>
    </Style>
    <Style x:Key="ButtonStyle2" TargetType="Button">
        <Setter Property="Background" Value="Red"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</ResourceDictionary>

Затем для Button, у которого есть это требование, вы привязываете Style к интересующему свойству

<Button ...
        Style="{Binding Path=MyDataProperty,
                        Converter={StaticResource ButtonStyleConverter}}"/>

И в конвертере вы загружаете словарь ресурсов ButtonStyles и возвращаете желаемый стиль на основе значения

public class ButtonStyleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Uri resourceLocater = new Uri("/YourNameSpace;component/ButtonStyles.xaml", System.UriKind.Relative);
        ResourceDictionary resourceDictionary = (ResourceDictionary)Application.LoadComponent(resourceLocater);
        if (value.ToString() == "Some Value")
        {
            return resourceDictionary["ButtonStyle1"] as Style;
        }
        return resourceDictionary["ButtonStyle2"] as Style;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Ответ 2

Более общий способ выполнить одно и то же:

SomeView.xaml

<UserControl>
  <UserControl.Resources>
    <converters:BooleanToStyleConverter x:Key="MyButtonStyleConverter" 
      TrueStyle="{StaticResource AmazingButtonStyle}" 
      FalseStyle="{StaticResource BoringButtonStyle}"/>
  </UserControl.Resources>
  <Grid>
    <Button Style={Binding IsAmazingButton, Converter={StaticResource MyButtonStyleConverter}}/>
  </Grid>
</UserControl>

BooleanToStyleConverter.cs

public class BooleanToStyleConverter : IValueConverter
{
    public Style TrueStyle { get; set; }
    public Style FalseStyle { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is bool && (bool) value)
        {
            return TrueStyle;
        }
        return FalseStyle;
    }

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

Этот конвертер работает в любом представлении с любым типом управления, используя любой стиль, который вы выберете, если вы привязываетесь к логическому свойству в ViewModel для управления переключением стиля. Легко адаптировать его к другим требованиям привязки. Это также работает в DataTemplate.