ViewModel의 bool 값에 Button의 가시성 바인딩


122

내 ViewModel의 bool 값에 단추의 가시성을 어떻게 바인딩합니까?

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

한 번 봐 가지고 CalcBinding
VivekDev

답변:


204

가정 AdvancedFormatA는 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으로 작업 할 때 매우 일반적인 패턴입니다. 이론적으로는 뷰 모델 속성에 직접 변환을 할 수있는 (즉, 단지 유형의 특성 자체를 만들어 Visibility내가 그렇게하지 선호하지만 이제부터) 되는 문제의 분리 덤비는. 항목의 가시성은 실제로보기에 달려 있어야합니다.


2
@ raym0nd 물론입니다. ViewModel은 조건을 나타내는 부울 만 반환합니다. 뷰가 해당 부울을 무언가를 표시할지 여부로 해석하는 경우 이는 뷰에 달려 있습니다. 다른 뷰는 여전히 다르게 해석 할 수 있습니다.
dlev

2
예, 이것은 가치를 마사지하는 도우미 클래스이기 때문입니다. 뷰 모델은 여전히 ​​모델과 뷰 사이에 있습니다.
CodeWarrior

2
또한 MVVM은 디자인 패턴이므로 구현과 관련된 자체 규칙을 적용해야합니다. 또한 무언가를 수행하는 유일한 방법이 Model, ViewModel 또는 View의 XAML 부분 밖에있는 경우도 있습니다. Codebehind에 무언가를 넣는 것은 죄가 아닙니다. 가능하면 ViewModel에 넣는 것이 MVVM 패턴과 더 일치합니다.
CodeWarrior

3
개인적으로 ViewModels에 Visibility 유형의 속성을 넣어도 괜찮습니다. 이것이 저의 이단이라는 것을 알고 있지만 저에게는 View에 더 많은 유연성을 제공합니다. View가 그것을 사용하고 싶지 않다면, 그것을 사용하지 않아도되며, 사용한다면 변환기 나 스타일 트리거를 가지고 놀아야하는 고통을 없앨 수 있습니다. 예, 이것은 내 ViewModel을 프레젠테이션 기술 (예 : WPF 대 ASP.Net MVC)에 약간 연결하지만 , 저를 놀라게하지 않는다면 이러한 기술과 리팩토링을 거의 혼합 할 필요 가 없습니다.
Jacob Proffitt 2011 년

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>

이 기술을 선호하는 경향이 있습니다. 바인딩 대상이 부울 이 아닌 많은 경우에 사용하기 때문입니다. 예를 들어 DataContextnull이 아닌 경우에만 요소를 표시 하거나 다른 레이아웃이 표시되는 다중 상태 디스플레이를 구현합니다. 뷰 모델에서 열거 형 설정.


5
일반적으로 변환기는 해킹이라고 느끼고 싫어합니다. 나는 이것이 공학적 관점에서 찬반 양론에 대한 냉정한 평가 라기보다는 내 괴팍한 개인적인 취향의 문제라고 생각하지만 나는 그것을 피한다.
Robert Rossney 2011-08-09

1
나는 그것들을 그렇게 자주 사용한다고 말할 수 없습니다. 그들은 약간 까다로운 경향이 있습니다 (원문?). 귀하의 게시물 이후, 이전 프로젝트에서 꽤 많은 스타일 / 트리거를 사용했음을 기억했습니다.
CodeWarrior

내가 가지고 TextBlock있는에 TextWrapping="Wrap"주어졌다. 이제 래핑 속성이 설정되지 않았습니다.
아 미트 JHA

10

부울에서 가시성으로 C #의 양방향 변환

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

일반적으로이를 수행하는 두 가지 방법이 있습니다. 변환기 클래스 또는 기본적으로 값을 변환하는 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 속성 메서드는 부울 속성 값을 확인하고이를 기반으로 가시성을 반환합니다. INotifyPropertyChanged를 구현하고 Boolean 및 Visibility 속성 모두에서 호출하여 올바르게 업데이트해야합니다.


12
WPF에는 이미 BooleanToVisibilityConverter가 내장되어 있습니다.
CodeNaked 2011 년

나는 그것을 깨닫지 못했다. 이것은 실제로이 시나리오에 맞게 편집 한 다른 것입니다. 미리 만들어진 것이 있으면 훨씬 좋습니다.
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. 다음은 참 / 거짓 값을 보유하는 부울 속성입니다. 다음은 코드 조각입니다. 내 예에서이 속성은 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.visible이에서 잘 작동합니다 UWP감사합니다.
rubStackOverflow

1

Windows 10 15063 이상

Windows 10 빌드 15063 이후에는 Visibility를 bool 값에 기본적으로 바인딩하는 "Implicit Visibility conversion"이라는 새로운 기능이 있습니다. 더 이상 변환기를 사용할 필요가 없습니다.

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