将Button的可见性绑定到ViewModel中的bool值


122

如何在ViewModel中将按钮的可见性绑定到bool值?

<Button Height="50" Width="50" Style="{StaticResource MyButtonStyle}"
    Command="{Binding SmallDisp}" CommandParameter="{Binding}" Cursor="Hand"
    Visibility="{Binding Path=AdvancedFormat}" />

Answers:


204

假设AdvancedFormatbool,则需要声明并使用BooleanToVisibilityConverter

<!-- In your resources section of the XAML -->
<BooleanToVisibilityConverter x:Key="BoolToVis" />

<!-- In your Button declaration -->
<Button
 Height="50" Width="50"
 Style="{StaticResource MyButtonStyle}"
 Command="{Binding SmallDisp}" CommandParameter="{Binding}" 
Cursor="Hand" Visibility="{Binding Path=AdvancedFormat, Converter={StaticResource BoolToVis}}"/>

注意添加 Converter={StaticResource BoolToVis}

在使用MVVM时,这是一种非常常见的模式。从理论上讲,您可以自己对ViewModel属性进行转换(即,仅使属性本身成为type Visibility),尽管我不希望这样做,因为现在您正在关注关注点的分离。项的可见性实际上应该取决于View。


2
@ raym0nd好的。ViewModel仅返回指示条件的布尔值。如果您的View恰好将布尔值解释为是否显示某些内容,则取决于View。请注意,另一个视图仍可以不同地解释它。
dlev 2011年

2
是的,因为这只是一个帮助提升价值的辅助课程。视图模型仍将位于模型和视图之间。
CodeWarrior

2
另外,请记住,MVVM是一种设计模式,因此您必须执行自己的有关其实现的规则。此外,有时候,完成某项任务的唯一方法将在View的Model,ViewModel或XAML部分之外。将某些东西放在“代码隐藏”中不是罪过。如果可能的话,将其放入MVVM模式更符合MVVM模式。
CodeWarrior

3
就个人而言,我不介意在ViewModels中放置Visibility类型的属性。我知道这是我的异端,但是对我来说,这为View提供了更多的灵活性,而不是更少。如果一个View不想使用它,则不必使用它,如果一个人使用它,则可以消除使用转换器或样式触发器的麻烦。是的,这关系我的视图模型来表示技术(WPF与ASP.Net MVC,例如)一点,但我很少需要混合的技术和重构如果我不吓唬我,太多。
雅各布·

1
BooleanToVisibilityConverter当前不适用于Windows Phone UI,但是此答案提供了一个实现stackoverflow.com/a/20344739/595473
CosworthTC

97

第三种方法不需要转换器或更改视图模型:使用样式:

<Style TargetType="Button">
   <Setter Property="Visibility" Value="Collapsed"/>
   <Style.Triggers>
      <DataTrigger Binding="{Binding IsVisible}" Value="True">
         <Setter Property="Visibility" Value="Visible"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

我倾向于使用此技术,因为在很多情况下,我要绑定的对象不是布尔值时就使用它-例如,仅当元素DataContext不为null 时才显示元素,或者实现基于状态的不同布局的多状态显示在视图模型中设置枚举。


5
通常,我觉得转换器是黑客,我不喜欢它们。我认为这是我的个人喜好而不是从工程的角度对利弊进行清醒的评估,但我避免这样做。
罗伯特·罗斯尼

1
我也不能说我经常使用它们。他们往往有点挑剔(原文如此?)。发布您的帖子后,我记得在以前的项目中使用了很多样式/触发器……
CodeWarrior

我有一个TextBlockTextWrapping="Wrap"给予。现在未设置包装属性。
阿米特·贾(Amit jha)2016年

10

C#中从布尔到可见性的2种方式转换

using System;
using System.Windows;
using System.Windows.Data;

namespace FaceTheWall.converters
{
    class BooleanToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Boolean && (bool)value)
            {
                return Visibility.Visible;
            }
            return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Visibility && (Visibility)value == Visibility.Visible)
            {
                return true;
            }
            return false;
        }
    }
}

7
如前所述,WPF中已经内置了一个。您不需要自己做。
鞋2014年

4

通常,有两种方法可以执行此操作,即转换器类或Viewmodel中的属性,该类实质上可以为您转换值。

如果是一次性转换,我倾向于使用属性方法。如果要重用它,请使用转换器。在下面,找到转换器的示例:

<ValueConversion(GetType(Boolean), GetType(Visibility))> _
Public Class BoolToVisibilityConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert

        If value IsNot Nothing Then
            If value = True Then 
                Return Visibility.Visible
            Else
                Return Visibility.Collapsed
            End If
        Else
            Return Visibility.Collapsed
        End If
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException
    End Function
End Class

ViewModel属性方法将只检查boolean属性值,并基于此返回可见性。确保实现INotifyPropertyChanged并在Boolean和Visibility属性上对其进行调用以正确更新。


12
WPF已经有了一个BooleanToVisibilityConverter内置的。
CodeNaked

我没有意识到。实际上,这是我为适应这种情况而编辑的其他内容。如果预建一个,那就更好了。
CodeWarrior

3

这可以通过非常简单的方法来实现。1.在视图中编写。

<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="50" Height="30">
<Button.Style>
        <Style TargetType="Button">
                <Setter Property="Visibility" Value="Collapsed"/>
                        <Style.Triggers>
                                <DataTrigger Binding="{Binding IsHide}" Value="True">
                                        <Setter Property="Visibility" Value="Visible"/>
                                    </DataTrigger>
                            </Style.Triggers>
            </Style>
    </Button.Style>

  1. 以下是布尔属性,其中包含true / false值。以下是代码段。在我的示例中,此属性在UserNote类中。

    public bool _isHide = false;
    
    public bool IsHide
    {
    
    get { return _isHide; }
    
    set
        {
            _isHide = value;
                OnPropertyChanged("IsHide");
        }
    } 
  2. 这是IsHide属性获取值的方式。

    userNote.IsHide = userNote.IsNoteDeleted;

2

在视图中:

<Button
 Height="50" Width="50"
 Style="{StaticResource MyButtonStyle}"
 Command="{Binding SmallDisp}" CommandParameter="{Binding}" 
Cursor="Hand" Visibility="{Binding Path=AdvancedFormat}"/>

在视图模型中:

public _advancedFormat = Visibility.visible (whatever you start with)

public Visibility AdvancedFormat
{
 get{return _advancedFormat;}
 set{
   _advancedFormat = value;
   //raise property changed here
}

您将需要进行属性更改事件

 protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
        PropertyChanged.Raise(this, e); 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
    } 

这就是他们使用Model-view-viewmodel的方式

但是,由于您希望将其绑定到布尔值,因此需要一些转换器。另一种方法是在外部设置布尔值,然后单击该按钮,然后将property_advancedFormat设置为所需的可见性。


private Visibility _advancedFormat = Visibility.visibleUWP谢谢,这很好。
rubStackOverflow

1

自Windows 10 15063起

自Windows 10内部版本15063起,就有一个称为“隐式可见性转换”的新功能,该功能将“可见性”本机绑定到bool值-不再需要使用转换器。

(请参阅https://social.technet.microsoft.com/wiki/contents/articles/34846.uwp-compiled-binding-windows-10-anniversary-update.aspx#Implicit_Visibility_conversion)。

我的代码(假定使用了MVVM,也使用了模板10):

<!-- In XAML -->
<StackPanel x:Name="Msg_StackPanel" Visibility="{x:Bind ViewModel.ShowInlineHelp}" Orientation="Horizontal" Margin="0,24,0,0">
    <TextBlock Text="Frosty the snowman was a jolly happy soul" Margin="0,0,8,0"/>
    <SymbolIcon Symbol="OutlineStar "/>
    <TextBlock Text="With a corncob pipe and a button nose" Margin="8,0,0,0"/>
</StackPanel>

<!-- in companion View-Model -->
public bool ShowInlineHelp // using T10 SettingsService
{ 
    get { return (_settings.ShowInlineHelp); }
    set { _settings.ShowInlineHelp = !value; base.RaisePropertyChanged(); }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.