WPF MVVM使用BooleanToVisibilityConverter隐藏按钮

33
在我的WPF应用程序中,我试图根据用户选择的选项更改按钮的可见性。在加载时,我希望其中一个按钮不可见。我正在使用内置值转换器BooleanToVisibilityConverter。然而它没有起作用,因为按钮在加载时出现了。我已经将属性更改为true和false,但没有任何区别。以下是我的代码,我看不到我错过了什么?
在我的视图模型中的属性
 bool ButtCancel
    {
        get { return _buttCancel; }
        set
        {
            _buttCancel = value;
            OnPropertyChanged("ButtCancel");
        }
    }

在我的app.xaml文件中

 <Application.Resources>       
    <BooleanToVisibilityConverter x:Key="BoolToVis"/>

在我的MainWindow.xaml文件中

 <Button Grid.Column="2" 
      Command="{Binding CommandButtProgressCancel}" 
      Content="Cancel" 
      Visibility="{Binding ButtCancel, Converter={StaticResource BoolToVis}}"
      IsEnabled="{Binding ButtCancelEnabled}" 
      Height="50" Width="120" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center" Margin="0,0,50,20"/>

3
你的 ButtCancel 属性是不是 public 的?根据你所提供的代码片段中没有任何访问修饰符,这会将其设置为默认的 private,从而无法被绑定引擎识别。另外,你也不应该绑定 IsEnabled 属性;应该让按钮使用你的命令的 CanExecute 回调来确定它自己的状态。 - Mike Strobel
@MikeStrobel,默认访问修饰符是internal而不是private - Sheridan
是的,我简直不敢相信我错过了那个!它不是公共的。 - mHelpMe
2
@Sheridan 对于顶层声明,默认为internal;对于类成员(包括嵌套类型声明),默认为private - Mike Strobel
2个回答

51

首先,如果您正在使用命令,则无需绑定IsEnabled属性,命令的实现应该决定是否启用此功能。

其次,ViewModel到View的绑定往往会在稍后阶段发生,因此最好为绑定设置默认值,如下所示:

Visibility="{Binding ButtCancel, Converter={StaticResource BoolToVis}, FallbackValue=Hidden}"

第三点,正如Mike所指出的那样,请确保您的属性是公共的,因为ViewModel和View是两个独立的类。


2
一个 internal 属性也不起作用。绑定引擎不知道绑定是在哪里声明的,因此所有非公共成员都被视为相同(实际上是 private)。 - Mike Strobel
哦,我不知道那个,谢谢Mike,我会调整我的答案。 - Stefan Z Camilleri

7

不需要使用转换器,只需使用DataTrigger

<Button Grid.Column="2" Command="{Binding CommandButtProgressCancel}" Content="Cancel" 
        Visibility="{Binding ButtCancel, Converter={StaticResource BoolToVis}}" 
        IsEnabled="{Binding ButtCancelEnabled}" Height="50" Width="120"
        HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,50,20">
    <Button.Style>
        <Style TargetType={X:Type Button}>
            <!-- This would be the default visibility -->
            <Setter Property="Visibility" Value="Visible" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding ButtCancel, UpdateSourceTrigger=PropertyChanged}" Value="True">
                    <Setter Property="Visibility" Value="Hidden" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

将您的ViewModel属性更新为public

public bool ButtCancel
{
    get { return _buttCancel; }
    set
    {
        _buttCancel = value;
        OnPropertyChanged("ButtCancel");
    }
}

请确保您的MainWindowDataContext已设置为ViewModel


如果你想使用MVVM模式(正如OP所说),触发器并不是最好的选择。 - 00jt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接