Question

I am trying to bind the IsEnabled property of a button to properties of the window's CollectionViewSource. I am doing this to implement First/Previous/Next/Last buttons and want the First and Previous to be disabled when the view is on the first item etc.

I have the collection view source set up, UI controls binding to it correctly, with access to its view in code so the click event handlers work fine in navigating through the view.

      <CollectionViewSource x:Key="cvMain" />

The DockPanel is the root element of the window

  <DockPanel DataContext="{StaticResource cvMain}">

FoJobs is an observable collection, cvJobs is a CollectionView that I use in the button's click handler

private void Window_Loaded(object sender, RoutedEventArgs e) {
  ((CollectionViewSource)Resources["cvMain"]).Source = FoJobs;
  cvJobs = (CollectionView)((CollectionViewSource)Resources["cvMain"]).View;
}

I have tried this but get a binding error "BindingExpression path error: '' property not found on 'object' ''ListCollectionView'"

        <Button Name="cbFirst" Click="cbMove_Click" IsEnabled="{Binding Source={StaticResource cvMain}, Converter={StaticResource CurrPos2BoolConverter}}" />

I am trying to do with a converter first but figure a style with triggers would be more efficient, but cant get access to the collection view. Even though the underlying datacontext is set to a collection view source, the binding is passed to the converter as the view's source (if I dont explicity set the binding's Source, as above), which has no currency properties (CurrentPosition, Count etc).

Any help would be greatly appreciated.

Was it helpful?

Solution

Why don't you use a RoutedCommand for this(even if you don't use MVVM that is)?

say something like:

<Button x:Name="nextButton"
        Command="{x:Static local:MainWindow.nextButtonCommand}"
        Content="Next Button" />

and in your code-behind:

public static RoutedCommand nextButtonCommand = new RoutedCommand();

public MainWindow() {
  InitializeComponent();
  CommandBinding customCommandBinding = new CommandBinding(
    nextButtonCommand, ExecuteNextButton, CanExecuteNextButton);
  nextButton.CommandBindings.Add(customCommandBinding);  // You can attach it to a top level element if you wish say the window itself
}

private void CanExecuteNextButton(object sender, CanExecuteRoutedEventArgs e) {
  e.CanExecute = /* Set to true or false based on if you want button enabled or not */
}

private void ExecuteNextButton(object sender, ExecutedRoutedEventArgs e) {
  /* Move code from your next button click handler in here */
}

You can also apply one of the suggestions from Explicitly raise CanExecuteChanged() to manually re-evaluate Button.isEnabled state.

This way your encapsulating logic relating to the button in one area.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top