【问题标题】:MahApps Metro HamburgerMenu Binding Not workingMahApps Metro HamburgerMenu 绑定不起作用
【发布时间】:2018-04-27 20:36:15
【问题描述】:

我不太确定这是不是问这个问题的最佳地点,但我想我会试一试。

我正在尝试使用 MahApps Metro UI Toolkit 在我的应用程序中实现一个汉堡菜单,该工具包在我制作的测试窗口中运行良好。于是我开始转到我的一个使用视图模型的主窗口。

问题是,HamburgerMenu 中的任何绑定根本不起作用,但在 HamburgerMenu 控件之外可以正常工作。

[示例视图:

这张图片显示了我为展示示例而制作的测试窗口模型。标题和两个文本框都绑定到“MyTitle”。如您所见,HamburgerMenu 中的那个不起作用。

我也尝试将 ViewModel 绑定到 HamburgerMenu 控件,但没有成功。我想它必须绑定到 HamburgerMenu ControlTemplate 中的“TheContentGrid”或“TheContent”控件,但这些控件不能从后面的代码中访问。

XAML:

<Controls:MetroWindow
        ..
        Title="{Binding MyTitle}"
        ..>
    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type Controls:HamburgerMenuGlyphItem}">
                <Grid Height="48">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="48" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                    <TextBlock Grid.Column="0" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Segoe MDL2 Assets" Text="{Binding Glyph}" />
                    <TextBlock Grid.Column="1" VerticalAlignment="Center" FontSize="16" Text="{Binding Label}" />
                </Grid>
            </DataTemplate>
        </Grid.Resources>

        <TextBox Text="{Binding MyTitle}" HorizontalAlignment="Right" />

        <Controls:HamburgerMenu Margin="0 30 0 0"
            SelectedIndex="0"
            x:Name="HamburgerMenuControl"
            ItemTemplate="{StaticResource MenuItemTemplate}"
            OptionsItemTemplate="{StaticResource MenuItemTemplate}"
            ItemClick="HamburgerMenuControl_OnItemClick"
            OptionsItemClick="HamburgerMenuControl_OnItemClick"
            DisplayMode="CompactOverlay">
            <!--  Items  -->
            <Controls:HamburgerMenu.ItemsSource>
                <Controls:HamburgerMenuItemCollection>
                    <Controls:HamburgerMenuGlyphItem Glyph="&#xE80F;" Label="Home">
                        <Controls:HamburgerMenuGlyphItem.Tag>
                            <Grid>
                                <TextBox Text="{Binding MyTitle}" HorizontalAlignment="Center" VerticalAlignment="Top"/>

                                <TextBlock Text="Home View" FontSize="32" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </Grid>
                        </Controls:HamburgerMenuGlyphItem.Tag>
                    </Controls:HamburgerMenuGlyphItem>
                </Controls:HamburgerMenuItemCollection>
            </Controls:HamburgerMenu.ItemsSource>

            <!--  Content  -->
            <Controls:HamburgerMenu.ContentTemplate>
                <DataTemplate DataType="{x:Type Controls:HamburgerMenuItem}">
                    <Grid x:Name="TheContentGrid">
                        <ContentControl x:Name="TheContent" Content="{Binding Tag}" />
                    </Grid>
                </DataTemplate>
            </Controls:HamburgerMenu.ContentTemplate>
        </Controls:HamburgerMenu>
    </Grid>
</Controls:MetroWindow>

代码隐藏和查看模型

public partial class WindowTest : MetroWindow
{
    public WindowTest()
    {
        InitializeComponent();

        DataContext = new TestViewModel();
    }

    private void HamburgerMenuControl_OnItemClick(object sender, ItemClickEventArgs e)
    {
        HamburgerMenuControl.Content = e.ClickedItem;
        HamburgerMenuControl.IsPaneOpen = false;
    }
}

public class TestViewModel : BindableBase
{

    private string myTitle;
    public string MyTitle
    {
        get { return myTitle; }
        set { SetProperty(ref myTitle, value); }
    }

    public TestViewModel()
    {
        MyTitle = "Title from VM";
    }
}

如果需要更多信息,请告诉我。

【问题讨论】:

  • ItemsSource 通常绑定到模型或视图模型的集合。不管你在里面塞什么东西,肯定不是它是怎么做的。
  • 遗憾的是没有关于如何做到这一点的教程,WPF 汉堡菜单的文档非常糟糕。

标签: c# wpf xaml mahapps.metro hamburger-menu


【解决方案1】:

也许我的回答对你来说有点晚,但可能会帮助其他人。 我自己偶然发现了这个问题,可以使用answer 中描述的解决方案来解决它。

因为HamburgerMenuGlyphItem 不会成为可视树或逻辑树的一部分,所以DataContext 没有绑定祖先。即您的绑定没有可绑定的源。

在资源中创建一个辅助对象的实例,并使用StaticResource 显式设置绑定源:

<Controls:MetroWindow.Resources>
    <local:BindingProxy x:Key="Proxy" Data="{Binding}" />
</Controls:MetroWindow.Resources>
...
    <Controls:HamburgerMenuGlyphItem.Tag>
        <Grid>
            <TextBox Text="{Binding Data.MyTitle, Source={StaticResource Proxy}}" />
        </Grid>
    </Controls:HamburgerMenuGlyphItem.Tag>

这里是帮助对象的代码 (source):

public class BindingProxy : Freezable
{ 
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

【讨论】:

    【解决方案2】:

    您应该解决实现 INotifyPropertyChanged 接口的问题。

    public class TestViewModel : BindableBase, INotifyPropertyChanged
    {
        public void SetPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new     PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private string myTitle;
        public string MyTitle
        {
            get { return myTitle; }
            set { 
                  SetProperty(ref myTitle, value); 
                  SetPropertyChanged("MyTitle");
                }
        }
    
        public TestViewModel()
        {
            MyTitle = "Title from VM";
        }
    }
    

    问题是您没有通知您的 UI 第一个文本框的 Text 属性已更改。 UI 在视图模型之前初始化,这就是为什么您会看到空文本框

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-27
      • 2021-12-17
      相关资源
      最近更新 更多