包含2个不同Datatemplates的列表框

时间:2014-12-16 10:51:59

标签: c# wpf

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

所以我做了以下事情:

Controls.cs

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;}
    }
}

和我的mainWindow.xaml

    <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中的事件未触发,并且未设置标签的背景。

有什么问题? 任何帮助都非常感谢。

提前致谢

2 个答案:

答案 0 :(得分:0)

第一个问题。
通常,从Visual及其后代(如Control)继承View Model层类型是一个坏主意。在视图模型层中定义视图模型:

// 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属性。这不是一个选项,因为您需要两个不同的模板;
  • 通过DataTemplateSelector属性使用ItemTemplateSelector;
  • 使用每种类型的默认模板,在资源字典中的某处声明。

你几乎是第三种方式,,你的模板有一个密钥,这不允许默认应用模板。要解决此问题,只需丢弃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>

有关数据模板的更多信息,请参阅此处:http://msdn.microsoft.com/en-us/library/ms742521%28v=vs.110%29.aspx

答案 1 :(得分:-1)

您绑定到IControl的集合,因此您添加到此集合中的任何内容都将被视为IControl,而不是它受尊重的类(MyButton或MyLabel)

因此,在界面上,列表中这些项目的类型是IControl,而不是MyButton或MyLabel,因此不应用样式。

也许您需要重新考虑您的UI设计?