【发布时间】:2014-12-15 03:55:56
【问题描述】:
对于这个冗长的问题,我深表歉意,但我觉得有必要包含所有这些信息。
直到现在,我一直在使用一种可能是非正统的方式将 UserControls 添加到我的应用程序中。假设我有一个名为Diagnostics 的用户控件,它有一个按钮,当单击该按钮时,将执行一个特定于拥有它的应用程序的功能。例如,如果我将 Diagnostics 放入 AppA,我希望它显示“A”,如果我将其放入 AppB,我希望 AppB 定义行为,使其显示“B”。
我通常通过传递给 UserControl 的构造函数的回调接口来实现这一点,这非常简单。这是一些可能无法编译的示例“代码”,但只是为了阐明我以前基本上做过的事情以及我正在尝试做的事情:
public interface IDiagnosticsCallback {
void DisplayDiagnostics(); // implemented by owner of Diagnostics UserControl
}
public class MyApp : IDiagnosticsCallback {
public void DisplayDiagnostics() {
MessageBox.Show("Diagnostics displayed specifically for MyApp here");
}
}
public Diagnostics : UserControl {
private IDiagnosticsCallback _callback { get; private set; }
public Diagnostics(IDiagnosticsCallback callback) {
_callback = callback;
}
public void ShowDiagnostics_Click(object sender, EventArgs e) {
_callback.DisplayDiagnostics();
}
}
我过去遇到的问题是理解如何在 XAML 中声明一个在其构造函数中接受参数的 UserControl(即没有默认构造函数),显然你不能。我用一种相当不优雅的方法解决了这个问题——我会在 XAML 中给主面板起一个名字,然后从代码隐藏中创建诊断,将必要的回调传递给它,然后我会将诊断添加到面板的列表中孩子的。严重违反了 MVVM 的用法,但它确实有效。
这个周末,我决定尝试学习如何为一个类和一个 TextBox 做这件事,结果我所要做的就是在我的 UserControl 中创建一个DependencyProperty 并使用数据绑定。它看起来像这样一些:
public ClassA
{
public void ShowSomethingSpecial()
{
MessageBox.Show("Watch me dance!");
}
}
public MyApp
{
public ClassA Foo { get; set; }
}
public Diagnostics : UserControl
{
public static readonly DependencyProperty SomethingProperty = DependencyProperty.Register("Something", typeof(ClassA), typeof(Diagnostics), new PropertyMetadata());
public ClassA Something
{
get { return (MyApp)GetValue(SomethingProperty); }
set { SetValue(SomethingProperty, value); }
}
// now uses default constructor
public void ShowSomethingSpecial_Click(object sender, EventArgs e)
{
Something.ShowSomethingSpecial();
}
}
MyApp.xaml
<diags:Diagnostics Something="{Binding Foo}" />
所以 Foo 是 MyApp 的一个属性,它数据绑定到 Diagnostics 的 Something DependencyProperty。当我单击 UserControl 中的按钮时,行为由 ClassA 定义。好多了,并且可以与 MVVM 一起使用!
我现在想做的是更进一步,而是将回调接口传递给我的 UserControl,以便它可以获取我的数字输入和输出的状态。我正在寻找这样的东西:
public Diagnostics : UserControl
{
public interface IDioCallback
{
short ReadInputs();
short ReadOutputs();
void SetOutput( char bit);
}
public IDioCallback DioCallbackInterface {
get { return (IDioCallback)GetValue(DioCallbackInterfaceProperty); }
set { SetValue(DioCallbackInterfaceProperty,value); }
}
// Using a DependencyProperty as the backing store for DioCallbackInterface. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DioCallbackInterfaceProperty = DependencyProperty.Register("DioCallbackInterface",typeof(IDioCallback),typeof(Diagnostics),new PropertyMetadata(0)); // PropertyMetadata is the problem...
}
public class DIO : IDioCallback
{
public short ReadInputs() { return 0; }
public short ReadOutputs() { return 0; }
public void SetOutput( char bit) {}
}
public class MyApp
{
public DIO MyDIO { get; set; }
}
MyApp.xaml
<diags:Diagnostics DioCallbackInterface="{Binding MyDIO}" />
虽然我的代码(可能不是上面的确切代码,而是我的真实项目)编译成功,但传递给 Register 的 PropertyMetadata 似乎有问题。我收到一个异常提示“默认值类型与属性'DioCallbackInterface'的类型不匹配。”
我是在做一些非常不正统的事情,还是这种数据绑定接口的方法实际上可行?如果不是,根据使用它的应用程序定义 UserControl 行为方式的推荐方法是什么?
【问题讨论】:
标签: wpf xaml c#-4.0 mvvm dependency-properties