Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有2个不同数据模板的listbox_C#_Wpf - Fatal编程技术网

C# 具有2个不同数据模板的listbox

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)

需要查看我需要添加到列表框的两个不同控件。 控件的类型为IControl

因此,我做了以下工作:

控制系统

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:键就成功了。。我现在不继承按钮和标签…再次感谢…抱歉我不能投票给你,但这是说这个解决方案确实有效…再次感谢