Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对Mahapps Metro HamburgerMenuIconItem的数据模板应用不同的绑定_C#_Wpf_Data Binding_Mahapps.metro - Fatal编程技术网

C# 对Mahapps Metro HamburgerMenuIconItem的数据模板应用不同的绑定

C# 对Mahapps Metro HamburgerMenuIconItem的数据模板应用不同的绑定,c#,wpf,data-binding,mahapps.metro,C#,Wpf,Data Binding,Mahapps.metro,我在MVVM WPF应用程序中使用Hamburger菜单,并使用DataTemplate将Badge控件应用于每个菜单项,如下所示:(摘自) ` ` 这很好,但这会将相同的值应用于所有菜单项-在本例中,我绑定到MessagingMainViewModel(包含HamburgerMenu控件标记的视图的视图模型)中名为TestCount的属性 ` ...` 每个菜单项都是一个视图,有自己的视图模型,我想绑定到ChatViewModel和InboxViewModel(但不是ComposeView

我在MVVM WPF应用程序中使用Hamburger菜单,并使用DataTemplate将Badge控件应用于每个菜单项,如下所示:(摘自)

`
`
这很好,但这会将相同的值应用于所有菜单项-在本例中,我绑定到MessagingMainViewModel(包含HamburgerMenu控件标记的视图的视图模型)中名为TestCount的属性

`
...`
每个菜单项都是一个视图,有自己的视图模型,我想绑定到ChatViewModel和InboxViewModel(但不是ComposeViewModel)中的一个公开属性,例如,一个名为UnreadCount的属性。我没有MessagingMainViewModel中的子视图模型(因为到目前为止应用程序中还没有需要)


我知道如何绑定到MessagingMainViewModel上的属性(如上面的DataTemplate代码所示),但找不到访问“子”视图的viewmodel的方法-更不用说在DataTemplate中使用它了。这可能吗?谢谢

您在
标记
-属性中设置了
内容
。我们可以在
数据模板
中使用它来访问
标记
-对象中的任何内容。您说您的标记是一个
UserControl
,因此我们可以访问它的
DataContext

下面是一个示例,假设您拥有的每个视图的属性都相同。如果没有,则需要使用
模板选择器


为了防止任何人遇到类似的问题,我使用Tag属性来访问相关的视图模型和属性,并实现了DataTemplateSelector,以便在是否显示badge/count控件之间进行选择(即对于ComposeMessageView不显示)。感谢蒂姆·U

我的最终代码:

<!-- Add reference to the custom DataTemplateSelector namespace -->
xmlns:helpers="clr-namespace:MyCompany.Wpf.Modules.Messaging.Helpers"

<!-- Include the template selector within Resouces (in my case within UserControl.Resources) -->
<helpers:HamburgerMenuIconItemTemplateSelector x:Key="MenuDataTemplateSelector"/> 

<!--  This is the template for the menu items (no badge/count control).  -->
<DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type Controls:HamburgerMenuIconItem}">
    <Grid Height="48">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="48" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ContentControl Grid.Column="0"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{Binding Icon}"
                        Focusable="False"
                        IsTabStop="False" />
        <TextBlock Grid.Column="1"
                   VerticalAlignment="Center"
                   FontSize="16"
                   Text="{Binding Label}" />
    </Grid>
</DataTemplate>

<!--  This is the template for the menu items (with badge/count control).  -->
<DataTemplate x:Key="MenuItemTemplateBadged" DataType="{x:Type Controls:HamburgerMenuIconItem}">
    <Grid Height="48">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="48" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Controls:Badged Grid.Column="0"
                         Badge="{Binding Tag.DataContext.UnreadMessagesCount}"
                         BadgeBackground="Red"
                         HorizontalAlignment="Center"
                         VerticalAlignment="Center">
            <ContentControl Content="{Binding Icon}"
                            Margin="2"
                            Focusable="False"
                            IsTabStop="False" />
        </Controls:Badged>
        <TextBlock Grid.Column="1"
                   VerticalAlignment="Center"
                   FontSize="16"
                   Text="{Binding Label}" />
    </Grid>
</DataTemplate> 

<Controls:HamburgerMenu x:Name="HamburgerMenuControl"
                    HamburgerWidth="48"
                    IsPaneOpen="True"
                    CanResizeOpenPane="True"
                    ItemInvoked="HamburgerMenuControl_OnItemInvoked"
                    ItemTemplateSelector="{StaticResource MenuDataTemplateSelector}"
                    SelectedIndex="0"
                    Style="{StaticResource MahApps.Styles.HamburgerMenu.Ripple}"
                    VerticalScrollBarOnLeftSide="False">
    <!--  Items  -->
    <Controls:HamburgerMenu.ItemsSource>
        <Controls:HamburgerMenuItemCollection>
            <Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=CommentAltSolid}" Label="Chat">
                <Controls:HamburgerMenuIconItem.Tag>
                    <views:ChatView />
                </Controls:HamburgerMenuIconItem.Tag>
            </Controls:HamburgerMenuIconItem>
            <Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=PenSquareSolid}" Label="Compose">
                <Controls:HamburgerMenuIconItem.Tag>
                    <views:ComposeMessageView />
                </Controls:HamburgerMenuIconItem.Tag>
            </Controls:HamburgerMenuIconItem>
            <Controls:HamburgerMenuIconItem Icon="{iconPacks:Material Kind=InboxArrowDown}" Label="Inbox">
                <Controls:HamburgerMenuIconItem.Tag>
                    <views:InboxView />
                </Controls:HamburgerMenuIconItem.Tag>
            </Controls:HamburgerMenuIconItem>
        </Controls:HamburgerMenuItemCollection>
    </Controls:HamburgerMenu.ItemsSource>
    ...


<!-- The custom data template selector class. -->
namespace MyCompany.Wpf.Modules.Messaging.Helpers
{
    using System.Windows;
    using System.Windows.Controls;

    using MyCompany.Wpf.Modules.Messaging.ViewModels;
    using MyCompany.Wpf.Modules.Messaging.Views;

    using MahApps.Metro.Controls;

    public class HamburgerMenuIconItemTemplateSelector: DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is HamburgerMenuIconItem)
            {
                var count = GetUnreadMessagesCount((HamburgerMenuIconItem)item);

                if (count == -1)
                {
                    return element.FindResource("MenuItemTemplate") as DataTemplate;
                }

                return element.FindResource("MenuItemTemplateBadged") as DataTemplate;
            }    

            return null;
        }

        private int GetUnreadMessagesCount(HamburgerMenuIconItem item)
        {
            // Get the view/user control
            var viewUserControl = (UserControl)item.Tag;

            // Get the data context. NOTE: All view models in the example
            // inherit from BaseMessageViewModel that exposes property 
            // UnreadMessagesCount - and this property is set to -1 when 
            // the view model is constructed.
            var dataContext = (BaseMessageViewModel)viewUserControl.DataContext;

            return dataContext.UnreadMessagesCount;
        }
    }
}

xmlns:helpers=“clr命名空间:MyCompany.Wpf.Modules.Messaging.helpers”
...
命名空间MyCompany.Wpf.Modules.Messaging.Helpers
{
使用System.Windows;
使用System.Windows.Controls;
使用MyCompany.Wpf.Modules.Messaging.ViewModels;
使用MyCompany.Wpf.Modules.Messaging.Views;
使用MahApps.Metro.Controls;
公共类HamburgerManuiconItemTemplateSelector:DataTemplateSelector
{
公共覆盖数据模板SelectTemplate(对象项,DependencyObject容器)
{
FrameworkElement=容器作为FrameworkElement;
如果(元素!=null&&item!=null&&item为HamburgerMenuIconItem)
{
var count=getUnderMessagesCount((HamburgerMenuIconItem)项);
如果(计数==-1)
{
返回元素.FindResource(“MenuItemTemplate”)作为DataTemplate;
}
返回元素.FindResource(“MenuItemTemplateBadged”)作为DataTemplate;
}    
返回null;
}
private int getUnderMessagesCount(HamburgerMenuIconItem项)
{
//获取视图/用户控件
var viewUserControl=(UserControl)item.Tag;
//获取数据上下文。注意:示例中的所有视图模型
//从公开属性的BaseMessageViewModel继承
//UnderMessageCount-并且当
//构建了视图模型。
var dataContext=(BaseMessageViewModel)viewUserControl.dataContext;
返回dataContext.UnreadMessagesCount;
}
}
}

另一个相关问题,如果您不介意的话,您可以使用TemplateSelector声明。我在hamburgermenu中有三个视图(选项),不希望显示其中一个视图(即视图:ComposeMessageView)的badge控件。我在网上搜索过,可以看到在代码隐藏中使用选择器的示例,以及在XAML中使用样式/数据触发器的示例。我试图让代码远离代码隐藏(MVVM方法)。您建议的ItemSelector方法是仅使用XAML还是包含一些代码?如果你能提供一个链接,将不胜感激。谢谢。我想你需要一些代码。我也是XAML的粉丝,但这就像用叉子吃饭一样。大多数时候,这是一个很好的选择,但如果你有汤,你最好用勺子:-)。回到toppic:这里有一个关于示例用法的链接:我已经按照链接的建议实现了一个templateselector,一切都很好。再次感谢@Tim。
`<Controls:HamburgerMenu x:Name="HamburgerMenuControl"
                                    HamburgerWidth="48"
                                    IsPaneOpen="True"
                                    CanResizeOpenPane="True"
                                    ItemInvoked="HamburgerMenuControl_OnItemInvoked"
                                    ItemTemplate="{StaticResource MenuItemTemplate}"
                                    OptionsItemTemplate="{StaticResource MenuItemTemplate}"
                                    SelectedIndex="0"
                                    Style="{StaticResource MahApps.Styles.HamburgerMenu.Ripple}"
                                    VerticalScrollBarOnLeftSide="False">
                <!--  Items  -->
                <Controls:HamburgerMenu.ItemsSource>
                    <Controls:HamburgerMenuItemCollection>
                        <Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=CommentAltSolid}" Label="Chat">
                            <Controls:HamburgerMenuIconItem.Tag>
                                <views:ChatView />
                            </Controls:HamburgerMenuIconItem.Tag>
                        </Controls:HamburgerMenuIconItem>
                        <Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=PenSquareSolid}" Label="Compose">
                            <Controls:HamburgerMenuIconItem.Tag>
                                <views:ComposeMessageView />
                            </Controls:HamburgerMenuIconItem.Tag>
                        </Controls:HamburgerMenuIconItem>
                        <Controls:HamburgerMenuIconItem Icon="{iconPacks:Material Kind=InboxArrowDown}" Label="Inbox">
                            <Controls:HamburgerMenuIconItem.Tag>
                                <views:InboxView />
                            </Controls:HamburgerMenuIconItem.Tag>
                        </Controls:HamburgerMenuIconItem>
                    </Controls:HamburgerMenuItemCollection>
                </Controls:HamburgerMenu.ItemsSource>
...`
<!-- Add reference to the custom DataTemplateSelector namespace -->
xmlns:helpers="clr-namespace:MyCompany.Wpf.Modules.Messaging.Helpers"

<!-- Include the template selector within Resouces (in my case within UserControl.Resources) -->
<helpers:HamburgerMenuIconItemTemplateSelector x:Key="MenuDataTemplateSelector"/> 

<!--  This is the template for the menu items (no badge/count control).  -->
<DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type Controls:HamburgerMenuIconItem}">
    <Grid Height="48">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="48" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ContentControl Grid.Column="0"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{Binding Icon}"
                        Focusable="False"
                        IsTabStop="False" />
        <TextBlock Grid.Column="1"
                   VerticalAlignment="Center"
                   FontSize="16"
                   Text="{Binding Label}" />
    </Grid>
</DataTemplate>

<!--  This is the template for the menu items (with badge/count control).  -->
<DataTemplate x:Key="MenuItemTemplateBadged" DataType="{x:Type Controls:HamburgerMenuIconItem}">
    <Grid Height="48">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="48" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Controls:Badged Grid.Column="0"
                         Badge="{Binding Tag.DataContext.UnreadMessagesCount}"
                         BadgeBackground="Red"
                         HorizontalAlignment="Center"
                         VerticalAlignment="Center">
            <ContentControl Content="{Binding Icon}"
                            Margin="2"
                            Focusable="False"
                            IsTabStop="False" />
        </Controls:Badged>
        <TextBlock Grid.Column="1"
                   VerticalAlignment="Center"
                   FontSize="16"
                   Text="{Binding Label}" />
    </Grid>
</DataTemplate> 

<Controls:HamburgerMenu x:Name="HamburgerMenuControl"
                    HamburgerWidth="48"
                    IsPaneOpen="True"
                    CanResizeOpenPane="True"
                    ItemInvoked="HamburgerMenuControl_OnItemInvoked"
                    ItemTemplateSelector="{StaticResource MenuDataTemplateSelector}"
                    SelectedIndex="0"
                    Style="{StaticResource MahApps.Styles.HamburgerMenu.Ripple}"
                    VerticalScrollBarOnLeftSide="False">
    <!--  Items  -->
    <Controls:HamburgerMenu.ItemsSource>
        <Controls:HamburgerMenuItemCollection>
            <Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=CommentAltSolid}" Label="Chat">
                <Controls:HamburgerMenuIconItem.Tag>
                    <views:ChatView />
                </Controls:HamburgerMenuIconItem.Tag>
            </Controls:HamburgerMenuIconItem>
            <Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=PenSquareSolid}" Label="Compose">
                <Controls:HamburgerMenuIconItem.Tag>
                    <views:ComposeMessageView />
                </Controls:HamburgerMenuIconItem.Tag>
            </Controls:HamburgerMenuIconItem>
            <Controls:HamburgerMenuIconItem Icon="{iconPacks:Material Kind=InboxArrowDown}" Label="Inbox">
                <Controls:HamburgerMenuIconItem.Tag>
                    <views:InboxView />
                </Controls:HamburgerMenuIconItem.Tag>
            </Controls:HamburgerMenuIconItem>
        </Controls:HamburgerMenuItemCollection>
    </Controls:HamburgerMenu.ItemsSource>
    ...


<!-- The custom data template selector class. -->
namespace MyCompany.Wpf.Modules.Messaging.Helpers
{
    using System.Windows;
    using System.Windows.Controls;

    using MyCompany.Wpf.Modules.Messaging.ViewModels;
    using MyCompany.Wpf.Modules.Messaging.Views;

    using MahApps.Metro.Controls;

    public class HamburgerMenuIconItemTemplateSelector: DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is HamburgerMenuIconItem)
            {
                var count = GetUnreadMessagesCount((HamburgerMenuIconItem)item);

                if (count == -1)
                {
                    return element.FindResource("MenuItemTemplate") as DataTemplate;
                }

                return element.FindResource("MenuItemTemplateBadged") as DataTemplate;
            }    

            return null;
        }

        private int GetUnreadMessagesCount(HamburgerMenuIconItem item)
        {
            // Get the view/user control
            var viewUserControl = (UserControl)item.Tag;

            // Get the data context. NOTE: All view models in the example
            // inherit from BaseMessageViewModel that exposes property 
            // UnreadMessagesCount - and this property is set to -1 when 
            // the view model is constructed.
            var dataContext = (BaseMessageViewModel)viewUserControl.DataContext;

            return dataContext.UnreadMessagesCount;
        }
    }
}