2017-08-25 171 views
2

我在使用Caliburn Micro的Conductor<>.Collection.OneActive與MahApps.Metro HamburgerMenu有幾個問題。從fewsamples,但他們都沒有解決我的情況。用Caliburn Micro進行MahApps.Metro HamburgerMenu

我的代碼全部來自於this Github repository。我想顯示一組HamburgerMenu裏面的一組窗格。每個窗格有一個標題和顯示名稱:

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; } 
} 

這有以下幾種觀點:

<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> 

我的外殼視圖模型也相當簡單。它從Conductor<IPane>.Collection.OneActive繼承,並採取了窗格的列表,它添加到其Items集合:現在

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屬性的雙向鏈接。

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每當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; 
    } 
} 

當我運行此代碼,並單擊漢堡包菜單中的項目中,頁面切換每次。問題是,當應用第一次運行時,沒有選定的窗格,並且您不能使用ShellViewModel中的任何激活覆蓋(例如OnViewAttachedOnActivate或事件構造函數)設置一個,因爲轉換器代碼掛鉤Tag尚未運行。

我對工作的解決方案要求:

  1. 卡利的導線必須負責,因爲有意見和視圖模型進一步下跌依賴於激活邏輯來運行堆棧。
  2. 應該是可能的ShellViewModel
  3. 激活期間在一些點以激活從卡利的第一項應該尊重的關注點分離,即視圖模型不應該知道,一個漢堡包菜單在視圖中被使用。

請參閱the GitHub repository瞭解應該立即運行的解決方案。

回答

0

我認爲這個問題是由控制內的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); 
    } 
} 
+0

你設法找到一個解決方案或解決方法嗎? punker76或MahApps的其他人是否已挑選此問題? – pinowthebird

+0

這將最終在v1.6.0中修復 – punker76

相關問題