2016-12-09 2 views
0

나는 처음 시작한 커뮤니티 툴킷을 사용하여 햄버거 메뉴를 구현했습니다. 이제 메뉴의 항목을 변경하는 기능을 추가하려고합니다. 예를 들어, OptionItem 중 하나에 로그인 상태를 표시하려고합니다. 로그인하지 않으 셨다면 로그인하고 싶다면 로그인을 원하면 로그인하십시오. 나는 표준 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를 추가해야했습니다. 버튼을 누르면 업데이트됩니다. 따라서 귀하의 답변은 효과가 있지만 완전한 해결책을 위해 약간의 수정이 필요합니다. 모드 = TwoWay. 'Model'클래스를 'Item'으로 변경하십시오. 템플리트의 데이터 유형을 '항목'으로 변경하십시오. INotifyPropertyChanged 인터페이스를 Item 클래스에 추가하십시오. 그럼 우리는 갈 수 있습니다 : D – BGTurner