0

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?

Swift Sharp
  • 2,604
  • 3
  • 30
  • 54

3 Answers3

2

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.

Mehrzad Chehraz
  • 5,092
  • 2
  • 17
  • 28
  • event if a set `public bool IsDeleteOptionEnable = false;` the context menu is still enable, can u download my sample – Swift Sharp May 18 '15 at 11:27
  • @SeeSharp You can't bind to a field, it must be a property. Try what bells posted with ListBox as binding element. You need to give the ListBox a name and then use Element=ListBoxName. – Mehrzad Chehraz May 18 '15 at 11:36
  • wtf, thanks mate, it's working with the ListBox's name, but why? – Swift Sharp May 18 '15 at 11:45
  • If none of the elements in the path from ListBox to LayoutRoot (except LayoutRoot itself) has no other DataContext defined, you code should still work. We can't say why it does not work unless full code provided. – Mehrzad Chehraz May 18 '15 at 11:51
1

Try

  IsEnabled="{Binding DataContext.IsDeleteOptionEnable, ElementName=LayoutRoot}"
Bells
  • 1,465
  • 1
  • 19
  • 30
0

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}" />
W0lfw00ds
  • 2,018
  • 14
  • 23