C# 具有2个不同数据模板的listbox
需要查看我需要添加到列表框的两个不同控件。 控件的类型为IControl 因此,我做了以下工作: 控制系统C# 具有2个不同数据模板的listbox,c#,wpf,C#,Wpf,需要查看我需要添加到列表框的两个不同控件。 控件的类型为IControl 因此,我做了以下工作: 控制系统 interface IControl { double X { get; set; } double Y { get; set; } } class MyButton : Button, IControl, INotifyPropertyChanged { public MyButton(string buttonText, double x, double y)
interface IControl
{
double X { get; set; }
double Y { get; set; }
}
class MyButton : Button, IControl, INotifyPropertyChanged
{
public MyButton(string buttonText, double x, double y)
{
this.Content = buttonText;
this.x = x;
this.y = y;
}
private double x = 0;
private double y = 0;
public MyButton()
{
}
public double X
{
get
{ return x;}
set
{
x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get { return y;}
set
{
y = value;
OnPropertyChanged("Y");
}
}
}
class MyLabel : Label, IControl, INotifyPropertyChanged
{
public MyLabel(int number, double x, double y)
{
this.Content = number.ToString(CultureInfo.InvariantCulture);
this.x = x;
this.y = y;
}
private double x = 0;
private double y = 0;
public MyLabel()
{
}
public double X
{
get{ return x;}
set
{
x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get{ return y;}
set
{
y = value;
OnPropertyChanged("Y");
}
}
}
现在在ViewModel.cs中
class ViewModel
{
private readonly ObservableCollection<IControl> controls = new ObservableCollection<IControl>();
public ViewModel()
{
var m1 = new MyButton("Test String inside button",0,0);
var m2 = new MyLabel(1123, 0, 80);
controls.Add(m1);
controls.Add(m2);
}
public ObservableCollection<IControl> Controls
{
get {return controls;}
}
}
类视图模型
{
私有只读ObservableCollection控件=新ObservableCollection();
公共视图模型()
{
var m1=新的MyButton(“按钮内的测试字符串”,0,0);
var m2=新的MyLabel(1123,0,80);
添加(m1);
控件。添加(m2);
}
公共可观测收集控制
{
获取{返回控件;}
}
}
在我的主窗口中
<ListBox
x:Name="listBox"
ItemsSource="{Binding Controls}"
SelectionMode="Extended"
>
<ListBox.Resources>
<DataTemplate x:Key="buttonTemplate" DataType="{x:Type local:MyButton}">
<Button Content="{Binding}"
MouseDown="button_MouseDown"
PreviewMouseUp="button_MouseUp"
PreviewMouseMove="button_MouseMove"
/>
</DataTemplate>
<DataTemplate x:Key="labelTemplate" DataType="{x:Type local:MyLabel}">
<Label Content="{Binding}" Background="Aqua"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style
TargetType="ListBoxItem"
>
<Setter
Property="Canvas.Left"
Value="{Binding X}"
/>
<Setter
Property="Canvas.Top"
Value="{Binding Y}"
/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
列表框显示了我添加到observableCollection中的MyButton和MyLabel,但是datatemplates什么也没做。
buttonTemplate中的事件未触发,且未设置标签的背景
怎么了?
非常感谢您的帮助
提前感谢您正在绑定到IControl的集合,因此您添加到此集合中的任何内容都将被视为IControl,而不是它的受尊重类(MyButton或MyLabel) 因此,在界面上,列表中这些项的类型是IControl,而不是MyButton或MyLabel,因此不应用样式 也许您需要重新考虑您的UI设计?第一个问题。
通常,从
Visual
及其子体(如Control
)继承视图模型图层类型是个坏主意。在视图模型图层中定义视图模型:
// former IControl, renamed to avoid confusing with view layer
public interface ICanvasItem
{
object Content { get; set; }
double X { get; set; }
double Y { get; set; }
}
public class MyButton : ICanvasItem, INotifyPropertyChanged { /* ... */}
public class MyLabel : ICanvasItem, INotifyPropertyChanged { /* ... */}
第二个问题。项控件的模板查找可以通过三种方式执行:
- 使用
属性。这不是一个选项,因为您需要两个不同的模板李>ItemTemplate
- 通过
属性使用ItemTemplateSelector
李>DataTemplateSelector
- 使用每个类型的默认模板,在资源字典中的某处声明
x:Key
属性,并将类型设为模板键:
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:MyButton}">
<Button Content="{Binding Content}"
MouseDown="button_MouseDown"
PreviewMouseUp="button_MouseUp"
PreviewMouseMove="button_MouseMove"
/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyLabel}">
<Label Content="{Binding Content}" Background="Aqua"/>
</DataTemplate>
</ListBox.Resources>
有关数据模板的更多信息可在此处阅读:是从
System.Windows.Controls.Button
继承而来的MyButton
,和<代码> MyLabor <代码> ->从代码>系统.Windows。控件。标签< /代码>是的。MyLabor和MyButle都是……我没有找到另一种方法来添加它们到一个观察表中,如果我没有找到它们之间的一个公共类型。当将数据模板应用到一个项目时,控件考虑运行时类型的IMTM。我不知道是谁给了你-- 1…但我会考虑你的建议,谢谢你。。。啊。。这是真实的Dennis,它将具有运行时类型……我认为情况并非如此,当然对于集合而言。如果他们要将其ObservableCollection更改为,并在添加按钮时注释掉,则应将样式应用于标签。我是不是遗漏了什么?@MikeEason:是的,你是。当某些控件必须呈现其内容并应用模板时,将使用内容的运行时类型(Object.GetType方法的结果)执行模板查找。谢谢。。。它现在起作用了。。。只是去掉了x:键就成功了。。我现在不继承按钮和标签…再次感谢…抱歉我不能投票给你,但这是说这个解决方案确实有效…再次感谢