Can't access datacontext of parent

2019-09-17 02:51发布

Basically what i have is a ListBox with ContextMenu

 <ListBox  Margin="2,0,0,0"  Grid.Row="1" ItemsSource="{Binding MyCollection}">
        <ListBox.ItemTemplate>
                <DataTemplate>
                    <Button  Style="{StaticResource NoVisualButton }" Tag="{Binding ID}" Width="430" toolkit:TiltEffect.IsTiltEnabled="True"  Margin="0,0,0,12" Click="OnSelectWorkOutItemClick">
                        <StackPanel>
                            <toolkit:ContextMenuService.ContextMenu>
                                <toolkit:ContextMenu>
                                    <toolkit:MenuItem Header="delete" Tag="{Binding ID}" Click="onContextMenuDeleteItemClick" IsEnabled="{Binding IsDeleteOptionEnable, ElementName=LayoutRoot}"/>
                                    <toolkit:MenuItem Header="edit"  Tag="{Binding ID}" Click="onContextMenuItemEditClick" />
                                </toolkit:ContextMenu>
                            </toolkit:ContextMenuService.ContextMenu>
                            ...
                        </StackPanel>
                    </Button>
                </DataTemplate>
       </ListBox.ItemTemplate>
 </ListBox>

So if MyCollection has only one item, i have to disable delete MenuItem.

My model has a property

   public bool IsDeleteOptionEnable
       {             
           get
           {
               return MyCollection.Count() >= 2;
           }
       }

In the page i am setting the DataContext like:

   protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (IsDataLoaded)
            {
                this.DataContext =MyModel;
            }           
        }

The listbox is getting populated, but i can't disable "delete" MenuItem. What am i doing wrong?

3条回答
老娘就宠你
2楼-- · 2019-09-17 03:02

Since the IsDeleteOptionEnable is a regular property, your view won't get notified when the property is changed. On options would be implementing INotifyPropertyChanged in your model (actually that should be ViewModel in an MVVM pattern) and calling the PropertyChanged event whenever items in your collection gets changed.

class YourModel : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged;
    ..
    ..
    public YourModel() {
        this.MyCollection = ...;
        this.MyCollection.CollectionChanged += MyCollection_CollectionChanged;
    }
    public bool IsDeleteOptionEnable {             
       get {
           return MyCollection.Count() >= 2;
        }
    }
    private void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
         this.OnPropertyChanged("IsDeleteOptionEnable");
    }
    private void OnPropertyChanged(string name = null) {
         if (this.PropertyChanged != null) {
            PropertyChangedEventArgs ea = new PropertyChangedEventArgs(name);
            this.PropertyChanged(this, ea);
         }
     }
}

Now when an item get removed or added to the collection, the model raises and PropertyChanged event so that the view will be aware that the IsDeleteOptionEnable property is (actually might) changed, and the enabled state of the button gets updated.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-09-17 03:07

Try

  IsEnabled="{Binding DataContext.IsDeleteOptionEnable, ElementName=LayoutRoot}"
查看更多
萌系小妹纸
4楼-- · 2019-09-17 03:12

As DataSource you need to use ObservableCollection. Then you need to implement INotifyPropertyChanged -interface in the class which contains the binded Property.

Example Class:

// Example of binded object
public class MyItem: INotifyPropertyChanged {

   // Binded Property
   private String itemIsVisible = "Yes";
   public String ItemIsVisible{
      get { return itemIsVisible; }
      set {
         itemIsVisible = value;

         // This ensures the updating
         OnPropertyChanged("ItemIsVisible");
      }
   }

   protected void OnPropertyChanged(string name) {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) {
         handler(this, new PropertyChangedEventArgs(name));
      }
   }
}

Example XAML:

<TextBlock Text="{Binding ItemIsVisible}" />
查看更多
登录 后发表回答