gpt4 book ai didi

c# - 使用 Caliburn Micro 执行 MahApps.Metro HamburgerMenu

转载 作者:太空宇宙 更新时间:2023-11-03 12:24:16 26 4
gpt4 key购买 nike

我在使用 Caliburn Micro 的 Conductor<>.Collection.OneActive 时遇到了一些问题与 MahApps.Metro HamburgerMenu .来自 few samples ,但它们都没有解决我的情况。

我的所有代码都在 this Github repository 中可用.

我想在 HamburgerMenu 中显示一组 Pane .每个 Pane 都有一个标题和一个显示名称:

public interface IPane : IHaveDisplayName, IActivate, IDeactivate
{
PackIconModernKind Icon { get; }
}

就我而言,IPane使用 PaneViewModel 实现:

public class PaneViewModel : Screen, IPane
{
public PaneViewModel(string displayName, PackIconModernKind icon)
{
this.Icon = icon;
this.DisplayName = displayName;
}

public PackIconModernKind Icon { get; }
}

这有以下 View :

<UserControl x:Class="CaliburnMetroHamburgerMenu.Views.PaneView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Padding="12"
Background="Pink">
<StackPanel Orientation="Vertical">
<TextBlock Text="Non-bound text" />
<TextBlock x:Name="DisplayName" FontWeight="Bold" />
</StackPanel>
</UserControl>

我的 shell View 模型也很简单。它继承自 Conductor<IPane>.Collection.OneActive , 并接收它添加到其 Items 的 Pane 列表收藏:

public class ShellViewModel : Conductor<IPane>.Collection.OneActive
{
public ShellViewModel(IEnumerable<IPane> pages)
{
this.DisplayName = "Shell!";

this.Items.AddRange(pages);
}
}

现在,这对我来说非常模糊。这是 ShellView.xaml 的摘录:

<controls:HamburgerMenu 
ItemsSource="{Binding Items, Converter={StaticResource PaneListToHamburgerMenuItemCollection}}"
SelectedItem="{Binding ActiveItem, Mode=TwoWay, Converter={StaticResource HamburgerMenuItemToPane}}">

<ContentControl cal:View.Model="{Binding ActiveItem}" />

<controls:HamburgerMenu.ItemTemplate>
<DataTemplate>
<Grid x:Name="RootGrid"
Height="48"
Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<iconPacks:PackIconModern
Grid.Column="0"
Kind="{Binding Icon}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White" />

<TextBlock Grid.Column="1"
VerticalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{Binding Label}" />
</Grid>
</DataTemplate>
</controls:HamburgerMenu.ItemTemplate>
</controls:HamburgerMenu>

为了完成这项工作,我依赖于两个转换器(坦率地说,他们做了比他们应该做的更多的事情)。一个转换器需要 ICollection<IPane>并创建一个 HamburgerMenuItemCollectionHamburgerMenuIconItem现在包含使用 Tag 的双向链接 View 模型和菜单项的属性。

class PaneListToHamburgerMenuItemCollection : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var viewModels = value as ICollection<IPane>;

var collection = new HamburgerMenuItemCollection();

foreach (var vm in viewModels)
{
var item = new HamburgerMenuIconItem();
item.Label = vm.DisplayName;
item.Icon = vm.Icon;
item.Tag = vm;
vm.Tag = item;
collection.Add(item);
}

return collection;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

第二个转换器使用这个 Tag 在 View 模型和菜单项之间进行转换每当 SelectedItem变化:

class HamburgerMenuItemToPane : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((IPane)value)?.Tag;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((HamburgerMenuIconItem)value)?.Tag;
}
}

当我运行此代码并单击汉堡菜单中的项目时,页面每次都会切换。问题是,当应用程序首次运行时,没有选定的 Pane ,并且您无法使用 ShellViewModel 中提供的任何激活覆盖来设置一个 Pane 。 (例如 OnViewAttachedOnActivate ,或事件构造函数),作为连接 Tag 的转换器代码还没有运行。

我对工作解决方案的要求:

  1. Caliburn 的指挥必须负责,因为在堆栈的更下方有 View 和 View 模型,它们依赖于运行的激活逻辑。
  2. 应该可以在激活 ShellViewModel 的某个时刻激活来自 Caliburn 的第一个项目。
  3. 应尊重关注点分离,即 View 模型不应知道 View 中正在使用汉堡菜单。

请参阅the GitHub repository一个应该立即运行的解决方案。

最佳答案

我认为问题是由控件内的 HamburgerMenu_Loaded 方法引起的。如果在控件加载之前有一个被选中的项目,汉堡菜单的内容被替换:

private void HamburgerMenu_Loaded(object sender, RoutedEventArgs e)
{
var selectedItem = this._buttonsListView?.SelectedItem ?? this._optionsListView?.SelectedItem;
if (selectedItem != null)
{
this.SetCurrentValue(ContentProperty, selectedItem);
}
}

在您的情况下,ContentControl 已被删除,您的 Conductor 无法完成其工作。

我正在尝试通过将代码更改为如下内容来查看是否可以直接在 MahApps 中更改此行为:

if (this.Content != null)
{
var selectedItem = this._buttonsListView?.SelectedItem ?? this._optionsListView?.SelectedItem;
if (selectedItem != null)
{
this.SetCurrentValue(ContentProperty, selectedItem);
}
}

关于c# - 使用 Caliburn Micro 执行 MahApps.Metro HamburgerMenu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45878823/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com