2009-11-19 6 views
6

MultiBinding의 하위 바인딩 업데이트를 건너 뛰는 방법은 무엇입니까? 나는 코드 숨김으로 정의했다. (나는 XAML에서 문제를 일으켰다. 문제가 없다고 생각한다. 모든 코드 숨김이 XAML보다 덜 표현한 후에) 두 개의 읽기 전용 속성과 하나의 일반 속성을 갖는 MultiBinding 단일 값을 생성합니다. ConvertBack의 경우 읽기 전용 속성은 수정되지 않고 (값을 유지함) 일반 속성 만 변경됩니다.읽기 전용 속성이있는 TwoWay MultiBinding

TwoWay에 전체가 MultiBindingMultiBinding 설정된 상태를 정의하지만 적절한 (처음 두 OneWay과 두 번째로 TwoWay) 특정 서브 세트의 바인딩.


문제가 자체 제어에서 발생합니다. 그러나 프리젠 테이션을 위해서 나는 그것을 더 작은 컨트롤로 단순화했다. 이 예제에서 제시된 컨트롤은 Slider과 같은 컨트롤로 [0.0; 1.0] 범위. 선택한 값은 엄지 손가락으로 표시되고 DependencyProperty으로 표시됩니다.

기본적으로 컨트롤은 1 행 x 3 열 Grid에 의해 빌드되며 엄지 손가락은 가운데 열에 있습니다. 엄지 손가락을 정확하게 위치 시키려면 왼쪽 열에 선택한 위치에 해당하는 너비를 지정해야합니다. 그러나이 너비는 전체 컨트롤의 실제 너비와 엄지 자체의 실제 너비에 따라 달라집니다 (위치가 [0.0; 1.0] 범위의 상대 값으로 주어지기 때문입니다).

엄지 손가락을 움직일 때 위치는 적절히 업데이트되어야하지만 엄지 손가락 폭과 조절 폭은 분명히 변경되지 않습니다.

엄지 손가락 이동 중에 IDE에서 실행될 때 코드가 예상대로 작동합니다. MultiBinding이 값을 두 개의 읽기 전용 속성으로 설정하려고 시도 할 때보고되는 예외 정보로 출력 창이 복잡해집니다. 나는 그것이 해롭지는 않다고 생각하지만 그것은 다소 귀찮고 오해의 소지가있다. 또한 코드가 다른 것을 수행한다는 것을 의미합니다. 그런 다음 해당 속성을 설정하지 않으려 고 했으므로 (실제로는 읽기 전용이 아니며 실제로 수정 될 수 있습니다.)

MultiBindingdocumentation 비고 섹션에서 개별 하위 바인딩이 MultiBinding 모드 값을 무시할 수는 있지만 작동하지 않는다는 것을 언급합니다.

컨트롤과 엄지 너비 (읽기 전용 속성)에 대한 의존성을 어떻게 든 다르게 표현하면 어쩌면 해결 될 수 있습니다. 예를 들어 개별적으로 알림에 등록하고 변경시 업데이트를 적용하는 경우. 그러나 그것은 내게 자연스럽지 않습니다. MultiBinding은 왼쪽 열 너비가이 세 가지 속성에 따라 달라 지므로 다른 한편으로 마찬가지입니다.


다음은 XAML 코드 예입니다. 여기

<UserControl x:Class="WpfTest.ExampleUserControl" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
    <ColumnDefinition x:Name="leftColumn" /> 
    <ColumnDefinition x:Name="thumbColumn" Width="Auto" /> 
    <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 
    <!-- Rectangle used in the left column for better visualization. --> 
    <Rectangle Grid.Column="0"> 
    <Rectangle.Fill> 
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> 
    <GradientStop Color="Black" Offset="0" /> 
    <GradientStop Color="White" Offset="1" /> 
    </LinearGradientBrush> 
    </Rectangle.Fill> 
    </Rectangle> 
    <!-- Thumb representing the Position property. --> 
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center" /> 
    <!-- Rectangle used in the right column for better visualization. --> 
    <Rectangle Grid.Column="2"> 
    <Rectangle.Fill> 
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> 
    <GradientStop Color="White" Offset="0" /> 
    <GradientStop Color="Black" Offset="1" /> 
    </LinearGradientBrush> 
    </Rectangle.Fill> 
    </Rectangle> 
</Grid> 
</UserControl> 

그리고

은 MultiBinding 잘 작동하지 않는 것처럼

using System; 
using System.Globalization; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace WpfTest 
{ 
public partial class ExampleUserControl : UserControl 
{ 
    #region PositionConverter 

    private class PositionConverter : IMultiValueConverter 
    { 
    public PositionConverter(ExampleUserControl owner) 
    { 
    this.owner = owner; 
    } 

    #region IMultiValueConverter Members 

    public object Convert(
    object[] values, 
    Type targetType, 
    object parameter, 
    CultureInfo culture) 
    { 
    double thisActualWidth = (double)values[0]; 
    double thumbActualWidth = (double)values[1]; 
    double position = (double)values[2]; 

    double availableWidth = thisActualWidth - thumbActualWidth; 

    double leftColumnWidth = availableWidth * position; 

    return new GridLength(leftColumnWidth); 
    } 

    public object[] ConvertBack(
    object value, 
    Type[] targetTypes, 
    object parameter, 
    CultureInfo culture) 
    { 
    double thisActualWidth = owner.ActualWidth; 
    double thumbActualWidth = owner.thumbColumn.ActualWidth; 
    GridLength leftColumnWidth = (GridLength)value; 

    double availableWidth = thisActualWidth - thumbActualWidth; 

    double position; 
    if (availableWidth == 0.0) 
    position = 0.0; 
    else 
    position = leftColumnWidth.Value/availableWidth; 

    return new object[] { 
    thisActualWidth, thumbActualWidth, position 
    }; 
    } 

    #endregion 

    private readonly ExampleUserControl owner; 
    } 

    #endregion 

    public ExampleUserControl() 
    { 
    InitializeComponent(); 

    MultiBinding leftColumnWidthBinding = new MultiBinding() 
    { 
    Bindings = 
    { 
    new Binding() 
    { 
     Source = this, 
     Path = new PropertyPath("ActualWidth"), 
     Mode = BindingMode.OneWay 
    }, 
    new Binding() 
    { 
     Source = thumbColumn, 
     Path = new PropertyPath("ActualWidth"), 
     Mode = BindingMode.OneWay 
    }, 
    new Binding() 
    { 
     Source = this, 
     Path = new PropertyPath("Position"), 
     Mode = BindingMode.TwoWay 
    } 
    }, 
    Mode = BindingMode.TwoWay, 
    Converter = new PositionConverter(this) 
    }; 
    leftColumn.SetBinding(
    ColumnDefinition.WidthProperty, leftColumnWidthBinding); 
    } 

    public static readonly DependencyProperty PositionProperty = 
    DependencyProperty.Register(
    "Position", 
    typeof(double), 
    typeof(ExampleUserControl), 
    new FrameworkPropertyMetadata(0.5) 
    ); 

    public double Position 
    { 
    get 
    { 
    return (double)GetValue(PositionProperty); 
    } 
    set 
    { 
    SetValue(PositionProperty, value); 
    } 
    } 

} 
} 

답변

9

마지막으로 해결책을 직접 찾았습니다. 실제로 그것은 documentation에 있습니다. 나는 그것을 어떻게 놓쳤는 지 모르지만 나는 그것에 대해 (쓸데없는 시간에) 값을 지불했습니다.

설명서에 따르면 은 값을 설정하지 않을 위치에 Binding.DoNothing을 반환해야합니다 (특히 OneWay 바인딩이 필요함). 또 다른 특별한 값은 DependencyProperty.UnsetValue입니다.

현재 완벽한 솔루션이 아니기 때문에 IMultiValueConverter 구현시 특수 값을 반환해야하는 위치를 알아야합니다. 그러나 나는이 합리적인 경우가이 해결책의 적용을받는다고 생각합니다.

+0

감사합니다. 이것은 내가 알 필요가있는 것이다! ConvertBack에서 해당 속성의 입력 값을 쉽게 얻을 수 있습니까? –

+1

고마워요! 값을 다시 변환하기를 원하는 개별 '내부'바인딩을 언급하는 것이 가치가 있을지도 모르지만,'Mode = TwoWay'로 설정해야합니다. 설명서에서 찾지 못했습니다. : / –

4

것 같습니다 해당 숨김 코드입니다. 제 연습 전에 예기치 않은 행동 (당신과 비슷한 것)을 보았습니다. 또한 변환기에 중단 점 또는 일부 추적을 삽입 할 수 있으며 변환기와 호출시기에 대한 재미있는 것을 찾을 수 있습니다. 가능한 경우 MultiBinding 사용을 피해야합니다. 예 :뷰 모델에서 세터에서 변경 가능한 속성의 값을 설정하고 getter에있는 세 가지 속성을 모두 사용하여 필요한 값을 반환하는 특수 속성을 추가 할 수 있습니다. 그것의 무언가 MultiValueConverter 속성 =) 내부.

희망이 있습니다.

+0

이것이 정말로 MultiBinding에서 어떤 종류의 버그라면 어쩌면 우리는 그것을 어떻게 든보고해야합니다. 이 작업을 수행 할 위치는? –

+0

.NET 4.0에서도 같은 작업을 시도 했습니까? 어쩌면 지금 고칠 수 있습니다. (내 VS 2010의 기술적 인 문제로 인해 지금은 시도 할 수 없습니다.) – levanovd