ボタンの可視性をViewModelのブール値にバインドする


122

ボタンの可視性をViewModelのブール値にバインドするにはどうすればよいですか?

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

見てみましょうCalcBinding
VivekDev

回答:


204

をと仮定するAdvancedFormatと、boolを宣言して使用する必要があります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)ことできます、懸念の分離に混乱しているので、私はそれを行いません。アイテムの可視性は、実際にはビュー次第です。


2
@ raym0ndもちろん。ViewModelは、条件を示すブール値のみを返します。ビューがそのブール値を何かを表示するかどうかと解釈する場合、それはビュー次第です。別のビューでも解釈が異なる場合があることに注意してください。
dlev、2011

2
はい、これは値をマッサージするヘルパークラスにすぎません。viewmodelは、モデルとビューの間に配置されます。
CodeWarrior

2
また、MVVMは設計パターンであるため、その実装に関して独自のルールを適用する必要があることに注意してください。さらに、何かを達成する唯一の方法が、モデル、ViewModel、またはビューのXAML部分の外にある場合もあります。コードビハインドに何かを入れることは罪ではありません。可能であれば、それをViewModelに配置することは、MVVMパターンとより一致します。
CodeWarrior

3
個人的には、Visibility型のプロパティをViewModelsに入れてもかまいません。私はそれが異端であることを知っていますが、私にとっては、これによりビューの柔軟性が向上します。ビューがそれを使用したくない場合は使用する必要はありません。使用したい場合は、コンバーターやスタイルトリガーを操作する手間を省きます。はい、このネクタイプレゼンテーション技術への私のViewModel(例えばASP.Net MVC対WPF)ビットが、私が今までならば、私はめったにそれらの技術をミックスする必要はないとリファクタリング、ずっと私を怖がらていません。
Jacob Proffitt 2011

1
BooleanToVisibilityConverterは現在Windows PhoneのUIでは使用できませんが、この回答により実装が提供されましたstackoverflow.com/a/20344739/595473
CosworthTC

97

コンバーターやビューモデルの変更を必要としない3つ目の方法があります。スタイルを使用します。

<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
一般に、コンバーターはハックであり、私は好きではないように感じます。これは、エンジニアリングの観点から賛否両論を冷静に評価するのではなく、私の気難しい個人的な好みの問題だと思いますが、私はそれらを避けます。
Robert Rossney、2011

1
よく使うとは言えません。彼らは一種の気難しい(sic?)の傾向があります。あなたの投稿の後、私は以前のプロジェクトでかなりの数のスタイル/トリガーを使用したことを思い出しました...
CodeWarrior

私は与えられTextBlockたものを持っていましたTextWrapping="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に組み込まれているものがあります。自分で作る必要はありません。

4

一般に、それを行う方法は2つあります。本質的に値を変換するコンバータークラスまたはViewmodelのプロパティです。

プロパティアプローチは、1回限りの変換の場合に使用する傾向があります。再利用したい場合は、コンバーターをご利用ください。以下に、コンバーターの例を示します。

<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プロパティメソッドは、ブールプロパティ値をチェックし、それに基づいて可視性を返します。必ずINotifyPropertyChangedを実装し、ブール値と可視性の両方のプロパティで呼び出して正しく更新してください。


12
WPFは、すでにしているBooleanToVisibilityConverterが組み込まれています。
CodeNaked

気づかなかった。これは実際には、このシナリオに合わせて編集したものです。1つが事前に作成されていれば、はるかに優れています。
CodeWarrior 2011

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値を保持するBooleanプロパティです。以下はコードスニペットです。私の例では、このプロパティは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の使用方法です

ただし、ブール値にバインドする必要があるため、コンバーターが必要になります。もう1つの方法は、ブール値を外側に設定し、そのボタンをクリックしたときに、property_advancedFormatを目的の可視性に設定することです。


private Visibility _advancedFormat = Visibility.visibleこれはUWP感謝の意を表します。
rubStackOverflow

1

Windows 10 15063以降

Windows 10ビルド15063以降、Visibilityをブール値にネイティブにバインドする「暗黙のVisibility変換」と呼ばれる新機能があります-コンバーターを使用する必要はもうありません。

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(); }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.