2016-12-30 61 views
0

我有按钮的KeyboardModel一个观察的集合,像这样绑定的各个按钮的视图

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

只有2键应该在这里,但在现实中这将是一个全键盘,并且每个键就像真正的键盘一样在屏幕上的固定位置。

我试图实现一个双向模型中的每个按钮,并在屏幕上相应的键之间具有约束力,但无法弄清楚如何做到这一点。

实质上,在模型中启用的任何按钮都应该在屏幕上的指定位置启用(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光和简化的发布。如何才能做到这一点?

+2

不要将Button控件放在视图模型集合中。它们是视图元素,而不是视图模型元素。而是使用您已注释掉的ItemTemplate方法,并创建一个表示按钮状态的(视图)模型类。 – Clemens

+1

为什么混合UI和实际逻辑?您可以定义类的按钮,例如:公共类VirtualButton,即实现INotifyPropertyChanged和具有的IsEnabled,Canvas_Top,Canvas_Left,宽度,高度,内容属性。所以,这样你就不必单独绑定每个按钮 – bamanow

+0

画布(或者要放在按钮无论容器)应ItemsControl中的ItemsPanel属性进行声明。 – Clemens

回答

1

做到这一点使用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; } 
} 

...和呈现每个键如使用一个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> 

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