在不同的上下文中绑定WPF属性

时间:2014-02-19 12:20:17

标签: c# wpf data-binding mvvm-light datacontext

我正在开发一个WPF应用程序并遇到了有关属性绑定的问题。我为我的应用程序设计了一个主菜单,我希望每个菜单项都有一个随机的左边距值(一个菜单项是一个按钮)。我还重新定义了Button模板。到目前为止,这是我的XAML代码:

MainMenuView.xaml:

<UserControl x:Class="OfficeTourismeBrantome.Views.MainMenuView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="800" d:DesignWidth="300">
<UserControl.Resources>
    <Style x:Key="MenuItemButtonStyle" TargetType="Button">
        <Setter Property="FontSize" Value="35" />
        <Setter Property="FontFamily" Value="Segoe" />
        <Setter Property="Foreground" Value="#FFEBEDEA" />           
        <Setter Property="HorizontalContentAlignment" Value="Right" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">                        
                        <Canvas HorizontalAlignment="Stretch" Background="Aqua">
                        <ContentPresenter Canvas.Left="{Binding MenuLayout.MenuItemLeftMargin}" HorizontalAlignment="Center"                                                  
                                      VerticalAlignment="Center"/>
                        </Canvas>                            
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<ItemsControl Name="menuButtonContainer" ItemsSource="{Binding Items}" Margin="{Binding MenuLayout.MenuMargin}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>        
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button 
                Style="{StaticResource ResourceKey=MenuItemButtonStyle}" 
                Margin="{Binding ElementName=menuButtonContainer, 
                                    Path=DataContext.MenuLayout.MenuItemMargin}"                    
                Height="{Binding ElementName=menuButtonContainer, 
                                    Path=DataContext.MenuLayout.MenuItemSize.Height}"
                Content="{Binding Text}"
                Command="{Binding ElementName=menuButtonContainer, 
                                    Path=DataContext.ChangeThemeCommand}"
                CommandParameter="{Binding Id}"
                />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

正如你所看到的,我在这里得到了2个不同的等级:

  1. 第一级,DataContext是UserControl一个(MainMenuViewModel)
  2. 第二个,DataContext位于列出MenuItems
  3. 的ItemControl中

    在这段代码中,只有一件事不起作用:Canvas ContentPresenter Canvas.Left属性绑定:

    <ContentPresenter Canvas.Left="{Binding MenuLayout.MenuItemLeftMargin}" HorizontalAlignment="Center"                                                  
                                      VerticalAlignment="Center"/>
    

    我的问题:

    1. 为什么以上绑定不起作用?在逐步,我看到正确分配的随机值。到目前为止,运行时没有变化,所以我没有实现INotifyPropertyChanged(实际上所有其他绑定都按预期工作)。
    2. 我意识到ItemTemplate中的一些属性(例如Height和Margin)应该在Style定义中。当我尝试它时,它不会绑定...
    3. 我是这样做的:

      <UserControl.Resources>
              <Style x:Key="MenuItemButtonStyle" TargetType="Button">    
      <Setter Property="Height" Value="{Binding MenuLayout.MenuItemSize.Height}" />
      </Style>
      </UserControl.Resources>
      

      我应该怎么做才能使这个绑定工作?

      谢谢你的回答!

      这是ViewsModels:

      MainMenuViewModel简化为utile东西(暴露MenuLayout属性):

      class MainMenuViewModel : LanguageChangedNotificationViewModelBase
      {      
      
          private MenuLayout _menuLayout;
      
          /// <summary>
          /// Menu items list property
          /// </summary>
          public ObservableCollection<MenuItem> Items
          {
              get { return _items; }
              set { _items = value; }
          }
      
          public MenuLayout MenuLayout
          {
              get
              {
                  return _menuLayout;
              }
              set
              {
                  _menuLayout = value;
              }
          }
      
          /// <summary>
          /// Constructor (that calls base constructor)
          /// </summary>
          public MainMenuViewModel() : base()
          {
              // New menu items list instance
              Items = new ObservableCollection<MenuItem>();
      
              // Menu layout var needed for display
              MenuLayout = new MenuLayout();
      
          }
      

      } }

      和MenuLayout类:

      namespace OfficeTourismeBrantome.Models
      

      {     class MenuLayout     {         私人厚度_menuMargin;

          private Thickness _menuItemMargin;
      
          private Size _menuItemSize;
      
          public Thickness MenuItemMargin
          {
              get {
                  _menuItemMargin.Left = GetRandomNumber();
                  return _menuItemMargin; 
              }
              set { _menuItemMargin = value; }
          }
      
      
          public Thickness MenuMargin
          {
              get { return _menuMargin; }
              set { _menuMargin = value; }
          }
      
          public Size MenuItemSize
          {
              get { return _menuItemSize; }
              set { _menuItemSize = value; }
          }
      
          public double MenuItemLeftMargin
          {
              get
              {
                  return GetRandomNumber();
              }
          }
      
          public MenuLayout()
          {
              MenuItemMargin = new Thickness(Properties.Settings.Default.mainMenuItemMarginLeft, Properties.Settings.Default.mainMenuItemMarginTop, Properties.Settings.Default.mainMenuItemMarginRight, Properties.Settings.Default.mainMenuItemMarginBottom);
              MenuMargin = new Thickness(Properties.Settings.Default.mainMenuMarginLeft, Properties.Settings.Default.mainMenuMarginTop, Properties.Settings.Default.mainMenuMarginRight, Properties.Settings.Default.mainMenuMarginBottom);
              MenuItemSize = new Size(100, 50);
          }
      
          private double GetRandomNumber()
          {
              double minimum = 0;
              double maximum = Properties.Settings.Default.mainMenuItemMarginLeft;
              Random random = new Random();
              return random.NextDouble(); //* (maximum - minimum) + minimum;
          }
      
      }
      

      }

0 个答案:

没有答案