开发者

WPF change Button Content on ViewModel.PropertyChanged event

My attempt (below) fails:

<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}" />

I'm trying to get the button to change when the IsReadOnly property on the ViewModel changes (it fires INotifyPropertyChanged.PropertyChan开发者_JAVA百科ged with "IsReadOnly" as the PropertyName). What am I missing?

.NET 3.5

ANSWER (at least for me - doesn't support the general case):

I just wrote a quick converter for boolean property binding.

[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}}" />


If you set the property "Content" of the Button, you cannot change it with a trigger, because the first one takes precedence.
Try to remove the setting of Content and it should work, because triggers will do the right work themselves.


You are using C# which means that the ToString() method for booleans return "true" and "false; whereas VB.NET they would be "True" and "False.

Your original code will work if you change your triggers to use the lowercase "true" and "false" instead of uppercase "True" and "False".

Tested with this code...

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# for the Window:

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

C# for the ViewModel class:

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"));
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜