WPF изменить содержимое кнопки для события ViewModel.PropertyChanged - PullRequest
2 голосов
/ 18 июля 2010

Моя попытка (ниже) не удалась:

<Canvas x:Key="Lock" ... />
<Canvas x:Key="Unlock" ... />

<Style x:Key="LockButtonStyle" TargetType="{x:Type Button}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="True">
            <DataTrigger.Setters>
                <Setter Property="Content" Value="{StaticResource Lock}" />                           
            </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="False">
            <DataTrigger.Setters>
                <Setter Property="Content" Value="{StaticResource Unlock}" />
            </DataTrigger.Setters>
        </DataTrigger>
    </Style.Triggers>
</Style>

...

<Button Content="{StaticResource Lock}" />

Я пытаюсь заставить кнопку измениться при изменении свойства IsReadOnly в ViewModel (оно запускает INotifyPropertyChanged.PropertyChanged с "IsReadOnly" в качестве PropertyName) Чего мне не хватает?

.NET 3.5

ОТВЕТ (по крайней мере для меня - не поддерживает общий случай):

Я только что написал быстрый конвертер для привязки логических свойств.

[ValueConversion(typeof(bool), typeof(object))]
public class BooleanValueConverter : IValueConverter
{
    public object FalseValue { get; set; }
    public object TrueValue { get; set; }

    #region IValueConverter Members

    public object Convert(object value, Type targetType, 
                          object parameter, CultureInfo culture)
    {
        return (bool)value ? this.TrueValue : this.FalseValue;
    }

    public object ConvertBack(object value, Type targetType, 
                              object parameter, CultureInfo culture)
    {
        return object.Equals(this.TrueValue, value) ? true : false;
    }

    #endregion
}

...

<local:BooleanValueConverter x:Key="LockOrUnlock" 
    TrueValue="{StaticResource Unlock}" 
    FalseValue="{StaticResource Lock}" />

...

<Button Content="{Binding Path=IsReadOnly, 
                             Converter={StaticResource LockOrUnlock}}" />

Ответы [ 2 ]

3 голосов
/ 18 июля 2010

Если вы установите свойство «Содержимое» кнопки, вы не сможете изменить его с помощью триггера, потому что первый имеет приоритет.Попробуйте удалить настройку Content, и она должна работать, потому что триггеры будут делать правильную работу сами.

1 голос
/ 07 марта 2018

Вы используете C #, что означает, что метод ToString () для логических значений возвращает «true» и «false», тогда как в VB.NET они будут «True» и «False».

Ваш оригинальный код будет работать, если вы измените триггеры на использование строчных букв "true" и "false" вместо прописных "True" и "False".

Протестировано с этим кодом ...

XAML:

<Window.Resources>
     <local:ViewModel x:Key="TheViewModel" />
    <Canvas x:Key="Lock">
        <TextBlock Text="Lock"/>
    </Canvas>
    <Canvas x:Key="Unlock">
        <TextBlock Text="Unlock"/>
    </Canvas>

    <Style x:Key="LockButtonStyle" TargetType="{x:Type Button}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="true">
                <DataTrigger.Setters>
                    <Setter Property="Content" Value="{StaticResource Lock}" />
                </DataTrigger.Setters>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="false">
                <DataTrigger.Setters>
                    <Setter Property="Content" Value="{StaticResource Unlock}" />
                </DataTrigger.Setters>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid DataContext="{StaticResource TheViewModel}">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Button x:Name="LockButton" Style="{StaticResource LockButtonStyle}" />
    <Button x:Name="ChangeIsReadOnly" Content="Change State" Grid.Row="1" Click="ChangeIsReadOnly_Click"/>
</Grid>

C # для окна:

public MainWindow()
{
    InitializeComponent();
}
private void ChangeIsReadOnly_Click(object sender, RoutedEventArgs e)
{
    ViewModel theViewModel = (ViewModel)FindResource("TheViewModel");
    theViewModel.IsReadOnly = !theViewModel.IsReadOnly;
}

C # для класса ViewModel:

public class ViewModel : System.ComponentModel.INotifyPropertyChanged
{
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    private bool isReadOnly;
    public bool IsReadOnly
    {
        get
        {
            return isReadOnly;
        }
        set 
        {
            isReadOnly = value;
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("IsReadOnly"));
        }
    }
}
...