带有 MVVM 的 Metro Flyouts
Metro Flyouts with MVVM
我正在尝试在我的应用程序中使用 MahApps.Metro 中的浮出控件。所以我将这部分添加到我的 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
将包含从我的视图模型到视图的映射。 Flyouts
是一个 ObservableCollection<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"
硬编码,但这也没有用。所以用数据模板显示浮出控件似乎是问题所在...
我按照 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
之间的映射器,因为我不想在我的视图模型界面中使用真实位置。
此外,视图现在不再需要是 Flyout
,它可以是普通的用户控件。
如果您在 Visible-属性
的 Setter 上调用 On属性Changed,您的第一个解决方案也应该能正常工作
我正在尝试在我的应用程序中使用 MahApps.Metro 中的浮出控件。所以我将这部分添加到我的 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
将包含从我的视图模型到视图的映射。 Flyouts
是一个 ObservableCollection<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"
硬编码,但这也没有用。所以用数据模板显示浮出控件似乎是问题所在...
我按照 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
之间的映射器,因为我不想在我的视图模型界面中使用真实位置。
此外,视图现在不再需要是 Flyout
,它可以是普通的用户控件。
如果您在 Visible-属性
的 Setter 上调用 On属性Changed,您的第一个解决方案也应该能正常工作