ViewModel'de bir Button görünürlüğünü bool değerine bağlama


122

ViewModel'imde bir düğmenin görünürlüğünü bool değerine nasıl bağlarım?

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

Bir göz atın CalcBinding
VivekDev

Yanıtlar:


204

A olduğunu varsayarsak AdvancedFormat, şunu boolbeyan etmeniz ve kullanmanız gerekir 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}}"/>

Eklenenlere dikkat edin Converter={StaticResource BoolToVis}.

Bu, MVVM ile çalışırken çok yaygın bir modeldir. Teorik olarak ViewModel mülkiyet dönüşüm kendiniz yapabileceğini (yani sadece tip özelliğini kendisi yapmak Visibilitybunu yapmamayı tercih ediyorum ama şimdi bu yana,) olan kaygıları ayrılığı karıştırmasını. Bir öğenin görünürlüğü gerçekten Görünüme bağlı olmalıdır.


2
@ raym0nd Elbette. ViewModel, yalnızca bir koşulu belirten bir boole döndürür. Görünümünüz bu boole'yi bir şey gösterip göstermeme olarak yorumlarsa, bu Görünüm'e bağlıdır. Başka bir Görünüm'ün yine de farklı yorumlayabileceğini unutmayın.
dlev

2
Evet, çünkü bu sadece bir değere masaj yapan yardımcı bir sınıf. Görünüm modeli yine de modeliniz ve görünümünüz arasında oturacaktır.
CodeWarrior

2
Ayrıca, MVVM'nin bir tasarım modeli olduğunu ve bu nedenle uygulanmasıyla ilgili kendi kurallarınızı uygulamanız gerektiğini unutmayın. Ek olarak, bir şeyi başarmanın tek yolunun Modelin, ViewModel'in veya Görünümün XAML kısmının dışında olacağı zamanlar olacaktır. Codebehind'e bir şey koymak günah değildir. Mümkünse onu ViewModel'e koymak MVVM modeliyle daha uyumludur.
CodeWarrior

3
Kişisel olarak, ViewModels'ime Visibility türü bir özellik koymaktan çekinmiyorum. Bunun benim kafir olduğumu biliyorum, ama bana göre bu bir Görüşe daha az değil, daha fazla esneklik sağlıyor. Bir View onu kullanmak istemezse, buna gerek yoktur ve eğer varsa, dönüştürücülerle veya stil tetikleyicileriyle oynamak zorunda kalmanın acısını ortadan kaldırır. Evet, bir sunum teknolojisi bu bağları benim ViewModel (WPF vs ASP.Net örneğin MVC,) biraz, ama nadiren bu teknolojilerin karıştırmak gerekiyor ve şimdiye kadar eğer üstlenmeden yapmak beni korkutmuyor çok.
Jacob Proffitt

1
BooleanToVisibilityConverter şu anda Windows Phone kullanıcı arayüzlerinde mevcut değil, ancak bu yanıt bir uygulama stackoverflow.com/a/20344739/595473
CosworthTC

97

Görünüm modelinizde bir dönüştürücü veya değişiklik gerektirmeyen üçüncü bir yol var: bir stil kullanın:

<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>

Bu tekniği tercih etme eğilimindeyim çünkü onu bağladığım şeyin boole olmadığı birçok durumda kullanıyorum - örneğin, bir öğeyi yalnızca DataContextboş değilse görüntüleme veya farklı düzenlerin görünüm modelinde bir numaralandırma ayarı.


5
Genel olarak, dönüştürücülerin bir hack olduğunu düşünüyorum ve onlardan hoşlanmıyorum. Sanırım bu, mühendislik açısından artıları ve eksileri ölçülü bir değerlendirmeden ziyade huysuz bir kişisel zevkim meselesi, ama onlardan kaçınıyorum.
Robert Rossney

1
Onları o kadar sık ​​kullandığımı da söyleyemem. Biraz titiz olma eğilimindedirler (sic?). Gönderinizden sonra, önceki projelerde epeyce stil / tetikleyici kullandığımı hatırladım ...
CodeWarrior

Bir vardı TextBlockhangi TextWrapping="Wrap"verildi. Artık sarma özelliği ayarlanmamış.
amit jha

10

Boolean'dan görünürlüğe c # 'de 2 yönlü dönüşüm

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
Daha önce de belirtildiği gibi, WPF'de zaten yerleşik bir tane var. Kendin yapmana gerek yok.
Shoe

4

Genellikle bunu yapmanın iki yolu vardır, bir dönüştürücü sınıfı veya Viewmodel'de değeri sizin için esasen dönüştüren bir özellik.

Bir defaya mahsus bir dönüşüm ise mülkiyet yaklaşımını kullanma eğilimindeyim. Yeniden kullanmak istiyorsanız, dönüştürücüyü kullanın. Aşağıda, dönüştürücü için bir örnek bulun:

<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

Bir ViewModel özellik yöntemi, yalnızca boole özelliği değerini kontrol eder ve buna göre bir görünürlük döndürür. INotifyPropertyChanged uyguladığınızdan ve doğru şekilde güncellenmesi için Boolean ve Visibility özelliklerinde çağırdığınızdan emin olun.


12
WPF zaten yerleşik bir BooleanToVisibilityConverter'a sahip.
CodeNaked

Bunu fark etmemiştim. Bu, aslında bu senaryoya uyacak şekilde düzenlediğim başka bir şeydi. Önceden yapılmış bir tane varsa çok daha iyi.
CodeWarrior

3

Bu çok basit bir şekilde başarılabilir 1. Bunu görünümde yazın.

<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. Aşağıda, doğru / yanlış değerini tutan Boolean özelliği verilmiştir. Aşağıdaki kod parçacığıdır. Örneğimde bu özellik UserNote sınıfındadır.

    public bool _isHide = false;
    
    public bool IsHide
    {
    
    get { return _isHide; }
    
    set
        {
            _isHide = value;
                OnPropertyChanged("IsHide");
        }
    } 
  2. Bu, IsHide özelliğinin değeri almasının yoludur .

    userNote.IsHide = userNote.IsNoteDeleted;

2

Görünümünde:

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

Görünüm Modelinde:

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

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

Bir mülk değişikliği etkinliğine ihtiyacınız olacak

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

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

Model-görünüm-görünüm modelini böyle kullanıyorlar

Ancak bir boolean ile bağlanmasını istediğiniz için, biraz dönüştürücüye ihtiyacınız olacak. Başka bir yol da boole değerini dışarıda ayarlamak ve bu düğmeye tıklandığında property_advancedFormat öğesini istediğiniz görünürlüğe ayarlamaktır.


private Visibility _advancedFormat = Visibility.visibleBu UWPteşekkür üzerine iyi çalışıyor .
rubStackOverflow

1

Windows 10 15063'ten beri

Windows 10 15063'ü oluşturduğundan, Görünürlüğü yerel olarak bool değerine bağlayan "Örtülü Görünürlük dönüşümü" adlı yeni bir özellik var - Artık dönüştürücü kullanmaya gerek yok.

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

Kodum (MVVM'nin kullanıldığını ve Şablon 10'un da kullanıldığını varsayar):

<!-- 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(); }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.