2016-12-09 4 views
0

私はうまく始まったコミュニティツールキットを使ってハンバーガーメニューを実装しました。 これで、メニューの項目を変更する機能を追加しようとしています。 たとえば、OptionItemの1つにログイン状態を表示したいとします。 ログインしていない場合はログインしてください。名前が表示されたい場合はログインしてください。 私は標準的なX追加しようとした:ラベルにバインドしますが、それは動作しません:UWP Community Tookit dynamic HamburgerMenuGlyphItemラベル

<controls:HamburgerMenuGlyphItem Label="{x:Bind Path=UserProfileViewModel.UserName}" Tag="SignIn" Glyph="Contact" /> 

ハンバーガーメニュー外のTextBlockにこれと同じバインディングが正常に動作し、彼らがログインした後、ユーザー名が表示されている使用

誰かが、どのようにMenuItems内でバインディングを実装するか考えていますか?

答えて

0

をmm8によって提供されるソリューションは実際に動作します。 しかし、それを働かせて私は、余分な努力をすることなく、最初の問題を解決する方法を発見しました。 DataTemplateのTextBlockバインディングにMode = TwoWay(OneWayも同様)を追加すると、プロパティが変更されたときにラベルが更新される問題を解決しました。 それから、HamburgerMenuGlyphItem自体のデータバインディングにもこの 'Mode'値の設定が必要であることがわかりました。一度私はそのバインディングにモードを追加し、ラベルは、ユーザーがサインインしても全く外部コードを必要としないときに更新を開始しました:)

1

誰かが、どのようにMenuItems内でバインディングを実装するか考えていますか?

HamburgerMenuのItemsSourceをIEnumerableに設定し、ItemTemplateのT型のプロパティにバインドできます。

ビュー:

<Page 
x:Class="App1.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:App1" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" 
mc:Ignorable="d"> 
<Page.Resources> 
    <DataTemplate x:Name="ItemTemplate" x:DataType="local:Item"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="48" /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <SymbolIcon Grid.Column="0" Symbol="{x:Bind Symbol}" /> 
      <TextBlock Grid.Column="1" Text="{x:Bind Label, Mode=TwoWay}" VerticalAlignment="Center" /> 
     </Grid> 
    </DataTemplate> 
</Page.Resources> 
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <controls:HamburgerMenu x:Name="hamburgerMenuControl" 
          ItemsSource="{Binding Items}" 
          SelectedItem="{Binding SelectedItem, Mode=TwoWay}" 
          ItemTemplate="{StaticResource ItemTemplate}" 
          ItemClick="hamburgerMenuControl_ItemClick"> 
     <ContentControl Content="{Binding SelectedItem.Content}" /> 
    </controls:HamburgerMenu> 
</Grid> 
</Page> 

public sealed partial class MainPage : Page 
{ 
    public MainPage() 
    { 
     this.InitializeComponent(); 
     this.DataContext = new ViewModel(); 
    } 

    private void hamburgerMenuControl_ItemClick(object sender, ItemClickEventArgs e) 
    { 
     //workaround to set the SelectedItem property of the view model when a new item is selected 
     (DataContext as ViewModel).SelectedItem = e.ClickedItem as Item; 
    } 
} 

ビューモデル:

public class ViewModel : INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
     Items.Add(new Item() { Label = "1", Symbol = Symbol.Bullets, Content = "1..." }); 
     Items.Add(new Item() { Label = "2", Symbol = Symbol.Bullets, Content = "2..." }); 
     Items.Add(new Item() { Label = "3", Symbol = Symbol.Bullets, Content = "3..." }); 
     SelectedItem = Items[0]; 
    } 

    public IList<Item> Items { get; } = new List<Item>(); 

    private Item _selectedItem; 
    public Item SelectedItem 
    { 
     get { return _selectedItem; } 
     set { _selectedItem = value; NotifyPropertyChanged(); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") => 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

モデル:

public class Item : INotifyPropertyChanged 
{ 
    private string _label; 
    public string Label 
    { 
     get { return _label; } 
     set { _label = value; NotifyPropertyChanged(); } 
    } 

    public Symbol Symbol { get; set; } 
    public object Content { get; set; } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") => 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

モデルのLabelプロパティを、ユーザー名またはオプションメニューに表示したいものに設定します。これは、推奨されるMVVMデザインパターンを使用してHamburgerMenuをデータバインドする方法です。

あなたのビューのXAMLマークアップで直接HamburgerMenuGlyphItemsを定義している場合は、同じビューのコードビハインドでプログラムバインディング設定結合することができる:だから

<controls:HamburgerMenuGlyphItem x:Name="item" /> 

public MainPage() 
    { 
     this.InitializeComponent(); 

     BindingOperations.SetBinding(item, HamburgerMenuGlyphItem.LabelProperty, 
      new Binding() { Path = new PropertyPath(nameof(Username)), Source = this }); 
    } 

    public string Username { get; } = "username..."; 
} 
+0

こんにちは、私はそれを働かせることはできません。新しいソリューションを作成し、提供されたコードを使用しました。 ItemクラスにINotifyPropertyChangedを追加しました。最後の項目のラベルを更新するボタンを追加しました。ボタンを押すと何も起こりませんでした。そこで別のコンテンツコントロールを追加し、それをラベル値にバインドしました。ハンバーガーメニューが無視されている間、ボタンが押されるとコンテンツコントロールが実際に更新されます。これは、標準のxを使用しようとするときに見られるのと同じ問題です。他のコントロールは更新されますが、ハンバーガーメニューは更新されません。 – BGTurner

+0

mm8、私の元のコメントが削除されてから削除され、5分後にSOがコメント編集をロックします。サンプルで使用しているコードは、ボタンクリックでラベルを更新するのと同じくらい簡単です。 ((ViewModel)this.DataContext).Items [2] .Label = "Signed In";内容コントロールには変更が示されますが、メニューにはまだ '3'が表示されます – BGTurner

+0

スクラッチで、DataTemplateのTextBlockバインディングにMode = TwoWayを追加する必要がありました。あなたの答えは機能しますが、完全な解決策のためにいくつかの修正が必要です。 Mode = TwoWay。 'Model'クラスを 'Item'に変更します。テンプレートのDataTypeを 'Item'に変更します。 INotifyPropertyChangedインタフェースをItemクラスに追加します。私たちは行くことができます:D – BGTurner

関連する問題