C# WPF数据绑定与编程生成控件
我的底层数据结构由一个基于公共抽象类的对象层次结构组成:C# WPF数据绑定与编程生成控件,c#,wpf,data-binding,C#,Wpf,Data Binding,我的底层数据结构由一个基于公共抽象类的对象层次结构组成: public abstract class model { public string name {get;}; public string type {get;}; } public class A:model { public int val1 {get; set;}; } public class B:model { public int val2 {get; set;}; } public cla
public abstract class model {
public string name {get;};
public string type {get;};
}
public class A:model {
public int val1 {get; set;};
}
public class B:model {
public int val2 {get; set;};
}
public class C:B {
public Dictionary<string, int> extra_props;
}
公共抽象类模型{
公共字符串名称{get;};
公共字符串类型{get;};
}
公共A类:模型{
公共int val1{get;set;};
}
B类公众:模型{
公共int val2{get;set;};
}
公共类C:B{
公共字典额外道具;
}
我的目标是创建一个UI,在选择对象时,它能够动态预览对象,但也能够修改对象的基础属性
关于WPF,我是一个绝对的noob,所以我不知道它的全部功能是什么。现在,关于单值属性,我找到了使用数据绑定将属性绑定到UI元素的方法。它就像一个显示和修改值的符咒
<GroupBox x:Name="InfoBox" Header="Object Information">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="41*"/>
<ColumnDefinition Width="200*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Grid.ColumnSpan="2" >
<TextBlock>Name:</TextBlock>
<TextBlock Text="{Binding name}" HorizontalAlignment="Right"></TextBlock>
</DockPanel>
<DockPanel Grid.Row="1" Grid.ColumnSpan="2" >
<TextBlock>Type:</TextBlock>
<TextBlock Text="{Binding type}" HorizontalAlignment="Right"></TextBlock>
</DockPanel>
<DockPanel Grid.Row="2" Grid.ColumnSpan="2" >
<TextBlock>Material Name:</TextBlock>
<TextBlock Text="{Binding val1}" HorizontalAlignment="Right"></TextBlock>
</DockPanel>
</Grid>
</GroupBox>
姓名:
类型:
材料名称:
问题1:
当绑定类型为B
的对象时,属性val1
不存在,并且调试输出中出现一些绑定错误。这些在执行过程中根本不会引起任何问题,但我没有找到捕获它们并返回默认值之类的方法
我所想到的解决这个问题的唯一方法是在抽象类中添加所有所需的属性,以便它们都存在于所有派生类中,并带有一些空值或其他内容,但这感觉一点也不正确
问题2:
对于更复杂的类,如C
,我希望基于类的属性集/列表动态生成UI。现在我完全不知道如何使用数据绑定,除了在XML中逐个添加它们并解决问题1
我想到的最可行的解决方案是以编程方式生成一个控件,并将其添加到主窗口中,其中包含我需要的类属性的文本框和输入,并且再次以编程方式希望能够将对象绑定到控件,以便正确地读取/设置值。显然,这种方法也可以解决问题1
我甚至不确定这个解决方案是否可行,但在任何情况下,我都需要一些建议和建议,主要是关于是否有办法解决数据绑定问题,或者是否应该以编程方式更新UI(如果可能).对于一个目前为止做得很好的noob来说:)实际上有一个非常简单的解决方案来解决这两个问题:数据模板。你可以读到关于他们的一切 在您的情况下,您希望为尝试显示的每种类型声明一个单独的模板:
<DataTemplate DataType="{x:Type local:A}">
<TextBlock Text="This object is type A">
</DataTemplate>
<DataTemplate DataType="{x:Type local:B}">
<TextBlock Text="This object is type B">
</DataTemplate>
这实际上是在说“好的,这是我的实际数据应该呈现的地方,但是我不想在这里特别声明它,而是希望您引用对象对应的DataTemplate”。通过这种方式,您可以使用单个ControlTemplate创建顶级按钮样式,但随后可以为要在其中呈现的每种类型的内容指定多个DataTemplates
许多控件使用DataTemplate,包括ListBox等,其中列表中的每个元素都可以根据其类型给出不同的图形表示。回到您自己的具体问题,如果您只想呈现数据本身,而不需要任何提示,那么只需使用ContentControl
:
<ContentControl Content="{Binding MyModel}" />
因此,
MyModel
应该是视图模型层中的类型为model
的属性(或设置DataContext的任何其他属性)。将该属性指定为类型A、B或C的实例将导致ContentControl中填充您在其DataTemplate中声明的任何内容的实例。首先,非常感谢您花时间写了这么好的回复。第二,这听起来非常简单。我必须测试一下,然后给你回复我的结果:灵巧。正好符合我的需要。老实说,我开始用编程生成的GUI实现我提出的解决方案。今天,我用DataTemplates做了完全相同的事情。我最终得到了完全相同的结果。我不确定它是否更有效率。当然,它提供了可重用的代码,无论我将来在哪里需要它。我只担心一件事。我不确定如何处理从基类派生的公共属性。现在,我必须将它们复制粘贴到每个数据模板上。我不确定这是否是因为基本模型类的抽象性质。这可以通过将公共元素(即绑定到模型
类的元素)放入它们自己的ControlTemplate中来实现。然后,您只需使用
将该模板插入到DataTemplates中,这正是我在网上找到的处理常见模板的解决方案,再次发挥了魅力。再次非常感谢,案件已经解决。
<ContentControl Content="{Binding MyModel}" />