显式设置WPF绑定数据类型

3
我想问一下,在绑定到类型为“object”的对象时,WPF是否具有任何功能可以定义binding的目标类型。我有一个类型为“object”的通用集合,在其各个绑定点必须以其中之一的对象类型(即DateTimeint等)处理。

是否有办法在处理绑定时,按照情况将未知类型的对象强制指定为Type_X的对象,并对其进行编译?


1
你可以制作一个转换器,根据传入的值的类型返回一个值。 - benjer3
4个回答

6
当然,你可以使用 DataTemplates。如果你在 App.xaml 中定义它们,它们将全局应用:
<DataTemplate DataType="{x:Type local:YourType}">
    <TextBox Text="{Binding SomeProperty}" HorizontalAlignment="Stretch"/>
</DataTemplate>

现在,无论何时您在 UI 中添加一个运行时类型为 YourType 的对象,比如在 StackPanel 中,该模板都将被使用。


抱歉,但那不是我正在寻找的。我正在尝试找到一种方法,使绑定到未指定类型“object”的属性的行为就像它是DateTime类型一样。 - tris
@user1039407,所以你有一个运行时类型为object的对象,并希望它表现得像日期时间?你从哪里获取实际的DateTime数据? - Botz3000

4

我不确定这是否完全符合您的要求,但您可以在绑定的Path属性中使用括号将属性名称括起来,并在前面添加<Type>.以指定类型。

例如:

<ContextMenu Tag="{Binding Path=PlacementTarget.(FrameworkElement.Tag), RelativeSource={RelativeSource Self}}">
...
</ContextMenu>

这表示属性TagFrameworkElement类型的成员,并指示PlacementTarget是该类型的一部分。

3
也许您可以使用d:DataContext设置设计时的DataContext——如果您只想让IDE知道它可以期望哪种数据。
<ContextMenu ItemsSource="{Binding Shapes}"
             DataContext="{Binding Data, Source={StaticResource BindingProxy}}"
             d:DataContext="{d:DesignInstance tree:DesktopViewModel}">
    [items...]
</ContextMenu>

我有一个ContextMenu,它的DataContext是从BindingProxy获取的(它具有类型为object的Data属性)。为了使VS和Resharper能够正确地工作,它们必须知道DataContext的类型,所以我只需定义一个设计时DataContext,现在它们知道它是DesktopViewModel

这仅适用于DataContext,而不适用于任何绑定(因为不存在DesignTimeBinding),但是您可以重写绑定以引用该DataContext(或将控件包装在具有DataContext和d:DataContext的网格中)。


2
不,Binding类没有提供任何此类功能;实际上它也不需要,绑定框架会自动将源对象转换为相关类型并使用绑定的属性值,否则会引发绑定错误,如果找不到该属性。所以,如果我在我的ViewModel中有一个Object 类型的属性。
public object Dummy 
{ 
    get 
    { 
        return dummy; 
    } 
    set 
    { 
        dummy = value;
        NotifyPropertyChanged("Dummy");
    } 
} 

我将它绑定到一个TextBox上,像这样 -
<TextBox Text="{Binding Dummy.Name}" HorizontalAlignment="Stretch"/>

然后将Dummy设置为对象,如下所示 -
Dummy = new MyCustomType();

在这一点上,绑定将评估并尝试在源对象(Dummy)中查找Name属性,如果MyCustomType定义了一个名为Name的公共属性,则绑定将执行,否则会发生绑定错误(不是异常,而是输出窗口中的错误消息)。
现在,假设我想将我的Dummy属性设置为两种不同类型的对象(一个具有Name,另一个具有FirstName),那么我有两个选项:
  1. 像Botz300建议的那样定义DataTemplates
  2. 使用一个ValueConverter(它检查对象类型并返回相关属性值)。
使用ValueConverter的另一种变体是定义一个TypeConverter来进行转换,并使用TypeConverterAttribute声明它,然后在绑定中将自动进行转换。
相同的方法也适用于对象的收集。
更新:
是的,WPF将隐式使用 DefaultType 转换器将您的类型转换为相关的显示值。如果您直接将 Object 绑定到属性(如上例中的 Text),则 WPF 将使用该类型的 TypeConverter(如果可用)或使用 ToString() 方法来获取显示值。
但所有这些都取决于您用于显示数据的控件以及如何/何时绑定。
请注意:此技巧仅适用于可以具有简单文本表示形式的对象。处理复杂数据对象时使用此便捷技术可能没有意义。
您可以阅读MSDN上的这篇文章,其中讨论了这个问题 - 使用数据绑定和WPF自定义数据显示

你的回答听起来非常好,似乎你已经理解了我的问题。在我的情况下,对象类型属性只能容纳“原始”类型,如整数、日期等。现在我只想让绑定框架表现得像属性是特定类型的。我猜这就是你所说的ValueConverter。你能给我提供任何示例吗?是否可以使用绑定框架似乎使用的“默认”转换器?还是我真的必须编写自己的新转换器? - tris
绑定不需要这样做。例如,ToolTip="{Binding Price,StringFormat=c}"StringFormat静默忽略,因为ToolTip是Object类型。调试输出中没有任何内容。我知道,“尽可能在非明显原因下进行静默失败”是XAML的关键设计目标之一,但这并不意味着这是一个好主意。是的,有几种方法可以解决StringFormat的特定问题。总是有的。 - 15ee8f99-57ff-4f92-890c-b56153

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接