问题
I'm trying to use the Flyouts from MahApps.Metro in my application. So I added this part to my 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>
The ItemTemplate
will contain the mappings from my viewmodels to the views. Flyouts
is an ObservableCollection<IFlyoutViewModel>
and currently only contains my SettingsViewModel
.
The IFlyoutViewModel
definition:
using System.ComponentModel;
namespace MyApplication.ViewModel
{
internal interface IFlyoutViewModel : INotifyPropertyChanged
{
bool Visible { get; set; }
}
}
And how I use the Visible
-property:
<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>
So now I set the Visible
-property of my SettingsViewModel, but the Flyout won't open. What am I doing wrong?
I just tried to assign IsOpen="true"
hardcoded but this didn't work, too. So displaying the flyout with a datatemplate seems to be the problem...
回答1:
I built it like described in the issue dicussion linked by Eldho, now it works. The key ist to define ItemContainerStyle
and bind IsOpen
there!
The new 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>
The new 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
}
}
The FlyoutPositionConverter
is just a mapper between my position enum and the MahApps.Metro.Controls.Position
because I didn't want to use the real positon in my viewmodel interface.
Also the view now no longer needs to be a Flyout
, it can be a normal usercontrol.
回答2:
Your first solution also should work well if you call OnPropertyChanged on the Setter of your Visible-Property
来源:https://stackoverflow.com/questions/36130858/metro-flyouts-with-mvvm