2

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.

Pe Ge
  • 23
  • 3
  • try to change the Source attribute to the ElementName. May be its help. – stukselbax Mar 31 '13 at 06:40
  • Where area you showing your data? `DataGrid` or ... – Hossein Narimani Rad Mar 31 '13 at 06:41
  • I dont understand how I can use ElementName as the collection view is declared in the window's resources, not as an element of the visual tree. – Pe Ge Mar 31 '13 at 09:29
  • I am displaying the list data in a datagrid with additional text boxes displaying properties of the current item, all working in synch with the navigation from the view. – Pe Ge Mar 31 '13 at 09:30

1 Answers1

2

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.

Community
  • 1
  • 1
Viv
  • 17,170
  • 4
  • 51
  • 71
  • Thanks Viv, that worked perfectly. I hitched a ride with the built in commands "LastPage" and "NextPage", rather than creating a custom command "nextButtonCommand" (though that may need to change). Didnt have to do anything to make CanExecuteChanged() work with the buttons enabled state. – Pe Ge Apr 01 '13 at 23:52