tl; dr : 강제 값은 데이터 바인딩간에 전파되지 않습니다. 코드 숨김이 바인딩의 다른 쪽을 모를 때 어떻게 데이터 바인딩을 통해 업데이트를 강제로 수행 할 수 있습니까?강제 값 강제 강제 적용
나는 WPF 종속성 속성에 CoerceValueCallback
을 사용하고 있는데 나는 바인딩을 통해 전파되지 않는 값을 강요 문제에 갇혔어요.
Window1.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace CoerceValueTest
{
public class SomeControl : UserControl
{
public SomeControl()
{
StackPanel sp = new StackPanel();
Button bUp = new Button();
bUp.Content = "+";
bUp.Click += delegate(object sender, RoutedEventArgs e) {
Value += 2;
};
Button bDown = new Button();
bDown.Content = "-";
bDown.Click += delegate(object sender, RoutedEventArgs e) {
Value -= 2;
};
TextBlock tbValue = new TextBlock();
tbValue.SetBinding(TextBlock.TextProperty,
new Binding("Value") {
Source = this
});
sp.Children.Add(bUp);
sp.Children.Add(tbValue);
sp.Children.Add(bDown);
this.Content = sp;
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
typeof(int),
typeof(SomeControl),
new PropertyMetadata(0, ProcessValueChanged, CoerceValue));
private static object CoerceValue(DependencyObject d, object baseValue)
{
if ((int)baseValue % 2 == 0) {
return baseValue;
} else {
return DependencyProperty.UnsetValue;
}
}
private static void ProcessValueChanged(object source, DependencyPropertyChangedEventArgs e)
{
((SomeControl)source).ProcessValueChanged(e);
}
private void ProcessValueChanged(DependencyPropertyChangedEventArgs e)
{
OnValueChanged(EventArgs.Empty);
}
protected virtual void OnValueChanged(EventArgs e)
{
if (e == null) {
throw new ArgumentNullException("e");
}
if (ValueChanged != null) {
ValueChanged(this, e);
}
}
public event EventHandler ValueChanged;
public int Value {
get {
return (int)GetValue(ValueProperty);
}
set {
SetValue(ValueProperty, value);
}
}
}
public class SomeBiggerControl : UserControl
{
public SomeBiggerControl()
{
Border parent = new Border();
parent.BorderThickness = new Thickness(2);
parent.Margin = new Thickness(2);
parent.Padding = new Thickness(3);
parent.BorderBrush = Brushes.DarkRed;
SomeControl ctl = new SomeControl();
ctl.SetBinding(SomeControl.ValueProperty,
new Binding("Value") {
Source = this,
Mode = BindingMode.TwoWay
});
parent.Child = ctl;
this.Content = parent;
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
typeof(int),
typeof(SomeBiggerControl),
new PropertyMetadata(0));
public int Value {
get {
return (int)GetValue(ValueProperty);
}
set {
SetValue(ValueProperty, value);
}
}
}
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
Window1.xaml
<Window x:Class="CoerceValueTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CoerceValueTest" Height="300" Width="300"
xmlns:local="clr-namespace:CoerceValueTest"
>
<StackPanel>
<local:SomeBiggerControl x:Name="sc"/>
<TextBox Text="{Binding Value, ElementName=sc, Mode=TwoWay}" Name="tb"/>
<Button Content=" "/>
</StackPanel>
</Window>
즉 두 사용자 컨트롤 다른 하나에 중첩하고, 그 윈도우의 외부 한 . 내부 사용자 정의 컨트롤에는 Value
종속성 속성이 있으며 외부 컨트롤의 종속성 속성 인 Value
에 바인딩되어 있습니다. 이 창에서 TextBox.Text
속성은 외부 컨트롤의 Value
속성에 바인딩됩니다.
내부 컨트롤의 Value
속성에 CoerceValueCallback
속성이 등록되어 있으며이 속성은 Value
속성에만 짝수를 할당 할 수 있습니다.
이 코드는 데모 용으로 단순화되어 있습니다. 실제 버전은 생성자에서 아무 것도 초기화하지 않습니다. 두 컨트롤에는 실제로 각 생성자에서 수행되는 모든 작업을 수행하는 컨트롤 템플릿이 있습니다. 즉, 실제 코드에서 외부 컨트롤은 내부 컨트롤을 알지 못합니다.
텍스트 상자에 짝수를 쓰고 포커스를 변경하면 (예 : 텍스트 상자 아래에있는 더미 버튼에 초점 맞추기) Value
속성이 정식으로 업데이트됩니다. 그러나 홀수를 텍스트 상자에 쓸 때 외부 컨트롤의 Value
속성과 TextBox.Text
속성은 홀수를 표시하는 반면 내부 컨트롤의 Value
속성은 변경되지 않습니다.
내 질문 : 텍스트 상자에서 업데이트를 강제로 수행 할 수 있습니까 (이상적으로 외부 컨트롤의 Value
속성에도 적용 할 수 있습니다).
나는 an SO question on the same problem을 찾았지만 해결책을 제시하지 못했습니다. 그것은 속성을 변경하는 이벤트 핸들러를 사용하여 값을 재설정하는 것을 암시하지만, 알 수있는 한, 이는 외부 컨트롤에 평가 코드를 복제하는 것을 의미합니다. 실제 평가 코드는 일부 코드에 의존하기 때문에 실제로 실행 가능하지 않습니다. 정보는 근본적으로 (많은 노력없이) 내부 통제에만 알려졌다.
또한, this blogpost 위의 암시대로 먼저 CoerceValueCallback
에 TextBox.Text
바인딩 만에 UpdateTarget
를 호출 제안, 내 내부 통제 가능성이 텍스트 상자에 대한 지식이 없으며, 둘째, 나는 아마 처음 UpdateSource
전화를 할 것입니다 내부 컨트롤의 속성 인 Value
의 바인딩그러나, 그 값을 CoerceValue
으로 리셋하는 경우에는 CoerceValue
메서드 내에서 강제 설정 값이 아직 설정되지 않았습니다 (바인딩을 업데이트하기에는 너무 빠름). 속성 값은 그대로 남아있게되므로 속성 변경 콜백이 호출되지 않습니다 (this discussion에 함축 됨). I는 통상의 특성 및 INotifyPropertyChanged
구현 SomeControl
에 의존 속성을 대체하고 생각 하였다
하나의 가능한 해결 방법은 (그래서 수동 값을 강요 한 경우에도 PropertyChanged
이벤트를 트리거 할 수있다). 그러나이 속성에 대한 바인딩을 더 이상 선언 할 수 없으므로 실제로 유용한 솔루션이 아닙니다.
당신이이 질문에 답을 찾으면 알려주세요.) –