[英]Change Source of Binding for attached property
如果我在附加屬性中使用綁定擴展
<TextBlock local:MyBehavior.View="{Binding A}" /> <!-- or B -->
如何從該附加行為設置ViewModel的A
(或B
)屬性的值?
我不明白:
Binding
? BindingBase
? BindingExpressionBase
? object
? SomeProperty
並在設置DataContext
讓綁定完成該工作? 我的嘗試失敗了 ,為方便起見,我在下面復制了它:
public class MyBehavior
{
public static BindingBase GetView(DependencyObject obj) => (BindingBase)obj.GetValue(ViewProperty);
public static void SetView(DependencyObject obj, BindingBase value) => obj.SetValue(ViewProperty, value);
public static readonly DependencyProperty ViewProperty =
DependencyProperty.RegisterAttached("View", typeof(BindingBase), typeof(MyBehavior), new PropertyMetadata(null, (d, e) =>
{
var element = d as FrameworkElement;
if (element == null)
throw new ArgumentException("Only used with FrameworkElement");
element.Loaded += (s, a) => GetView(element); // <<
}));
}
我不確定在標記行設置綁定屬性給定值的操作:
public class ViewModel
{
public object A { get; set; }
public object B { get; set; }
}
附加屬性使用哪種類型?
與您在視圖模型中定義source屬性的類型相同,即object
或附加屬性應存儲的任何類型的值。 類型取決於您打算在附加屬性中存儲的值的類型。
我應該立即設置值嗎
注冊依賴項屬性時,可以為其指定默認值。 引用類型(例如object)的默認值通常為null
:
public class MyBehavior
{
public static object GetView(DependencyObject obj) => obj.GetValue(ViewProperty);
public static void SetView(DependencyObject obj, object value) => obj.SetValue(ViewProperty, value);
public static readonly DependencyProperty ViewProperty =
DependencyProperty.RegisterAttached("View", typeof(object), typeof(MyBehavior),
new PropertyMetadata(/*default value: */ null, new PropertyChangedCallback(OnPropertyChanged)));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//...
}
}
當您綁定到視圖模型時,依賴屬性的值將像其他任何依賴屬性一樣自動設置,例如:
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public object A { get; set; } = "value...";
}
MainWindow.xaml:
<TextBlock local:MyBehavior.View="{Binding A}" />
public class MyBehavior
{
public static object GetView(DependencyObject obj) => obj.GetValue(ViewProperty);
public static void SetView(DependencyObject obj, object value) => obj.SetValue(ViewProperty, value);
public static readonly DependencyProperty ViewProperty =
DependencyProperty.RegisterAttached("View", typeof(object), typeof(MyBehavior),
new PropertyMetadata(/*default value: */ null, new PropertyChangedCallback(OnPropertyChanged)));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
object theValue = GetView(d);
MessageBox.Show(theValue.ToString());
}
}
如果希望將視圖模型屬性設置為附加屬性的值,則應將綁定的模式設置為OneWayToSource
:
<TextBlock x:Name local:MyBehavior.View="{Binding A, Mode=OneWayToSource}" />
但是隨后是更新視圖模型的視圖:
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyBehavior.SetView(txt, "new value...");
}
附加的依賴項屬性本身就是可以在任何DependencyObject上設置的另一個依賴項屬性。
編輯:
該解決方案仍然需要代碼隱藏,我的意圖是通過附加行為來消除它。 有想法嗎? 注意element.Loaded(另請參閱我對@dymanoid的評論),想法是從附加行為中設置值,並且僅使用綁定來傳遞源(定義哪個屬性A或B應該獲得該值)。
然后,您可以簡單地將附加屬性設置為源屬性的名稱:
<TextBlock local:MyBehavior.View="A" />
...並使用反射在您附加的行為中設置此source屬性的值:
public class MyBehavior
{
public static object GetView(DependencyObject obj) => obj.GetValue(ViewProperty);
public static void SetView(DependencyObject obj, object value) => obj.SetValue(ViewProperty, value);
public static readonly DependencyProperty ViewProperty =
DependencyProperty.RegisterAttached("View", typeof(object), typeof(MyBehavior),
new PropertyMetadata(/*default value: */ null, new PropertyChangedCallback(OnPropertyChanged)));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as FrameworkElement;
if (element == null)
throw new ArgumentException("Only used with FrameworkElement");
element.Loaded += (s, a) =>
{
string propertyName = GetView(element).ToString();
if(element.DataContext != null)
{
System.Reflection.PropertyInfo pi = element.DataContext.GetType().GetProperty(propertyName);
pi.SetValue(element.DataContext, "new value...");
}
};
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.