Wpf 将ObservableCollection中的各个按钮绑定到视图

Wpf 将ObservableCollection中的各个按钮绑定到视图,wpf,data-binding,mvvm-light,Wpf,Data Binding,Mvvm Light,我在键盘模型中有一组可观察到的按钮,就像这样 using System.Collections.ObjectModel; using System.Windows.Controls; namespace SODemo { public class KeyboardModel { public KeyboardModel() { Buttons = new ObservableCollection<Button>

我在键盘模型中有一组可观察到的按钮,就像这样

using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace SODemo
{
    public class KeyboardModel
    {
        public KeyboardModel()
        {
            Buttons = new ObservableCollection<Button>();
            Buttons.Add(new Button() { Name = "X", Content = "X", IsEnabled = true });
            Buttons.Add(new Button() { Name = "Y", Content = "Y", IsEnabled = false});
        }
        public ObservableCollection<Button> Buttons { get; set; }
    }
}
使用System.Collections.ObjectModel;
使用System.Windows.Controls;
名称空间SODemo
{
公共类键盘模型
{
公用键盘模型()
{
按钮=新的ObservableCollection();
添加(新按钮(){Name=“X”,Content=“X”,IsEnabled=true});
添加(新按钮(){Name=“Y”,Content=“Y”,IsEnabled=false});
}
公共可观察收集按钮{get;set;}
}
}
这里应该只有两个键,但实际上它将是一个完整的键盘,每个键都将在屏幕上的一个固定位置,就像一个真正的键盘一样

我试图在模型中的每个按钮和屏幕上相应的键之间实现双向绑定,但不知道如何做到这一点

本质上,模型中启用的任何按钮都应在屏幕上的指定位置启用(CanExecute=true)。如视图所示,我不能使用Name参数(编译器错误)将视图中的键映射到模型中相应的按钮

这是键盘视图

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SODemo"
    Height="300"
    MinWidth="800">

    <UserControl.Resources>
        <local:KeyboardModel x:Key="KeyboardModel" />
    </UserControl.Resources>

    <ItemsControl>
        <!--          
        <ItemsControl.ItemTemplate>
                <DataTemplate DataType="Button">
                    <Button Content="{Binding Path=Does not work}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>-->

        <Canvas x:Name="DrawnKeyboard" DataContext="{StaticResource KeyboardModel}" IsEnabled="False">

            <!-- this displays first item in collection "X" as expected.. but not what I need-->
            <Button Canvas.Left="14" Canvas.Top="54" Width="64" Height="50" Content="{Binding Buttons[0]}" Name ="X"> 

            <!--Compiler error "MarkupExtensions are not allowed for Uid or Name property values, so '{Binding Path=Name}' is not valid." -->
            <Button Canvas.Left="82" Canvas.Top="54" Width="64" Height="50" Name="{Binding Path=Name}"/>


        </Canvas>
    </ItemsControl>
</UserControl>


真正的项目是使用MVVM light和simplified进行发布。如何实现这一点?

使用MVVM模式实现这一点的方法是定义一个表示键的模型类:

public class Key
{
    public string Name { get; set; }
    public bool IsEnabled { get; set; }
    public double Left { get; set; }
    public double Top { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
}
…并从视图模型中显示一个ObservableCollection:

public class KeyboardModel
{
    public KeyboardModel()
    {
        Keys = new ObservableCollection<Key>();
        Keys.Add(new Key() { Name = "X", IsEnabled = true, Width = 65, Height = 50, Top = 54, Left = 14 });
        Keys.Add(new Key() { Name = "Y", IsEnabled = false, Width = 65, Height = 50, Top = 54, Left = 82  });
    }

    public ObservableCollection<Key> Keys { get; set; }
}
公共类键盘模型
{
公用键盘模型()
{
Keys=新的ObservableCollection();
添加(newkey(){Name=“X”,IsEnabled=true,Width=65,Height=50,Top=54,Left=14});
添加(newkey(){Name=“Y”,IsEnabled=false,Width=65,Height=50,Top=54,Left=82});
}
公共ObservableCollection密钥{get;set;}
}
…并使用ItemsControl和ItemTemplate在视图中将每个键显示为按钮:

<ItemsControl ItemsSource="{Binding Keys}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Width="700" Height="700" Background="Yellow" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Left" Value="{Binding Left}" />
            <Setter Property="Canvas.Top" Value="{Binding Top}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="Button">
            <Button Content="{Binding Name}" IsEnabled="{Binding IsEnabled}" 
                            Width="{Binding Width}" Height="{Binding Height}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>


如注释中所述,按钮等控件仅属于视图。

不要将按钮控件放置在视图模型集合中。它们是视图图元,而不是视图模型图元。而是使用您注释掉的ItemTemplate方法,创建一个(视图)模型类来表示按钮的状态?您可以为按钮定义类,例如:公共类VirtualButton,它实现INotifyPropertyChanged,并具有IsEnabled、Canvas_Top、Canvas_Left、Width、Height和Content的属性。因此,这样您就不必单独绑定每个按钮画布(或您希望将按钮放入的任何容器)应该在ItemsControl的ItemsPanel属性中声明。“ItemTemplate方法对我不起作用”。好吧,那就让它工作吧。这就是路。你现在有的是垃圾。。