带有MVVM的Metro Flyouts

时间:2016-03-21 12:19:35

标签: c# wpf xaml mvvm mahapps.metro

我正在尝试在我的应用程序中使用来自MahApps.Metro的Flyouts。所以我将这部分添加到了我的MainWindow.xaml:

<controls:MetroWindow.Flyouts>
    <controls:FlyoutsControl ItemsSource="{Binding Flyouts}">
        <controls:FlyoutsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type viewModel:SettingsViewModel}">
                <view:SettingsFlyout/>
            </DataTemplate>
        </controls:FlyoutsControl.ItemTemplate>
    </controls:FlyoutsControl>
</controls:MetroWindow.Flyouts>

ItemTemplate将包含从我的视图模型到视图的映射。 FlyoutsObservableCollection<IFlyoutViewModel>,目前仅包含我的SettingsViewModel

IFlyoutViewModel定义:

using System.ComponentModel;

namespace MyApplication.ViewModel
{
    internal interface IFlyoutViewModel : INotifyPropertyChanged
    {
        bool Visible { get; set; }
    }
}

以及我如何使用Visible - 属性:

<controls:Flyout x:Class="MyApplication.View.SettingsFlyout"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
                 Header="Settings"
                 Position="Right"
                 IsOpen="{Binding Visible}"
                 Width="300">
    ...
</controls:Flyout>

所以现在我设置了我的SettingsViewModel的Visible - 属性,但Flyout将无法打开。我做错了什么?

我只是尝试分配IsOpen="true"硬编码,但这也不起作用。因此,使用datatemplate显示弹出窗口似乎是问题......

2 个答案:

答案 0 :(得分:1)

我像Eldho关联的问题描述中所描述的那样构建它,现在它可以工作。关键是定义ItemContainerStyle并绑定IsOpen

新的MainWindow.xaml

<controls:MetroWindow.Flyouts>
    <controls:FlyoutsControl ItemsSource="{Binding Flyouts}">
        <controls:FlyoutsControl.Resources>
            <view:FlyoutPositionConverter x:Key="FlyoutPositionConverter"/>
        </controls:FlyoutsControl.Resources>
        <controls:FlyoutsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type viewModel:SettingsViewModel}">
                <view:SettingsFlyout/>
            </DataTemplate>
        </controls:FlyoutsControl.ItemTemplate>
        <controls:FlyoutsControl.ItemContainerStyle>
            <Style BasedOn="{StaticResource {x:Type controls:Flyout}}"
               TargetType="{x:Type controls:Flyout}">
                <Setter Property="Header"
                    Value="{Binding Header}" />
                <Setter Property="IsOpen"
                    Value="{Binding Visible}" />
                <Setter Property="Position"
                    Value="{Binding Position, Converter={StaticResource FlyoutPositionConverter}}" />
                <Setter Property="IsModal"
                    Value="{Binding IsModal}" />
                <Setter Property="Theme" Value="Accent" />
            </Style>
        </controls:FlyoutsControl.ItemContainerStyle>
    </controls:FlyoutsControl>
</controls:MetroWindow.Flyouts>

新的IFlyoutViewModel

using System.ComponentModel;

namespace MyApplication.ViewModel
{
    internal interface IFlyoutViewModel : INotifyPropertyChanged
    {
        string Header { get; }
        bool Visible { get; set; }
        Position Position { get; set; }
        bool IsModal { get; set; }
    }

    public enum Position
    {
        Top,
        Left,
        Right,
        Bottom
    }
}

FlyoutPositionConverter只是我的位置枚举和MahApps.Metro.Controls.Position之间的映射器,因为我不想在我的viewmodel界面中使用真正的位置。

此外,视图现在不再需要是Flyout,它可以是普通的用户控件。

答案 1 :(得分:0)

如果您在Visible-Property的Setter上调用OnPropertyChanged,您的第一个解决方案也应该可以正常工作