WPF DataBinding与ItemsSource的交互

时间:2014-10-05 03:19:43

标签: c# wpf xaml mvvm data-binding

在我的ListBox中,我有需要绑定到ItemsSource和Viewmodel中的属性的控件。您可以看到按钮需要同时执行这两个操作。我似乎能够做到这一点的唯一方法是非常难看(参见IsEnabled属性绑定到视图的视图模型)。我想知道最好的办法是什么。

编辑:澄清我想将IsEnabled属性绑定到CanRemove。

<Button IsEnabled="{Binding CanRemove}"></Button>

这不起作用

由于

XAML

<ListBox x:Name="songListBox" ItemsSource="{Binding SongList, Mode=TwoWay}" SelectedItem="{Binding SelectedSongAndNumber, Mode=TwoWay}" SelectionChanged="songListBox_SelectionChanged" Tag="{Binding OperationState, Mode=TwoWay}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>

                .......

                <Label Grid.Column="1" Width="200" Height="40" Content="{Binding Number, Mode=TwoWay}"/>

                <TextBox Grid.Column="3" Width="200" Height="40" Text="{Binding Name, Mode=TwoWay}"/>

                <Button Grid.Column="5" x:Name="btnMerge" Click="btnMerge_Click" Content="{Binding Tag, Converter={StaticResource ButtonConverter}, ElementName=songListBox}" IsEnabled="{Binding DataContext,Converter={StaticResource EnableConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:AlbumTrackAssociationView}}}">
                    <Button.Visibility>
                        <MultiBinding Converter="{StaticResource B2V}">
                            <Binding Path="Number"/>
                            <Binding ElementName="songListBox"/>
                        </MultiBinding>
                    </Button.Visibility>
                </Button>

                <Button Grid.Column="7" x:Name="btnDelete" Click="btnDelete_Click" IsEnabled="{Binding DataContext, Converter={StaticResource EnableConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:AlbumTrackAssociationView}}}">Delete
                    <Button.Visibility>
                        <MultiBinding Converter="{StaticResource B2V}">
                            <Binding Path="Number"/>
                            <Binding ElementName="songListBox"/>
                        </MultiBinding>
                    </Button.Visibility>
                </Button>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

视图模型

public class AlbumTrackAssociationViewModel : ViewModelBase
{
    public class SongAndNumber : ViewModelBase
    {

        private string number;

        public string Number
        {
            get { return number; }
            set { 
                number = value;
                RaisePropertyChanged("Number");
            }
        }

        private string name;

        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                RaisePropertyChanged("Name");
            }
        }
    }

    private int _numberOfSongs { get; set; }

    public bool CanRemove
    {
        get { return SongList != null && (SongList.Count <= _numberOfSongs ? false : true); }
    }

    public ObservableCollection<SongAndNumber> SongList { get; set; }
}

转换器

public class ItemButtonConverter : IValueConverter
{
    public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
    {
        AlbumTrackAssociationViewModel vm = (AlbumTrackAssociationViewModel)value;
        return vm.CanRemove;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

3 个答案:

答案 0 :(得分:1)

当你做mvvm并想要使用按钮时,你应该使用DelegateCommand或RelayCommand。如果你使用它,那么你只需要正确实现ICommand(CanExecute!)命令绑定到按钮将为你处理IsEnabled。

  <Button Command="{Binding MyRemoveCommand}"></Button>

CS。

  public ICommand MyRemoveCommand {get;set;}

  this.MyRemoveCommand = new DelegateCommand(this.RemoveCommandExecute, this.CanRemoveCommandExecute);

  private bool CanRemoveCommandExecute()
  {
      return this.CanRemove;
  }

  private bool RemoveCommandExecute()
  {
      if(!this.CanRemoveCommandExecute)
        return;

     //execution logic here
  }

答案 1 :(得分:1)

当您可以使用 RelativeSource 标记扩展程序直接访问ViewModel时,您根本不需要转换器。这应该有效:

<Button IsEnabled="{Binding DataContext.CanRemove,
              RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}"/>

由于ListBox的DataContext指向viewModel实例,因此上面发布的代码将起作用。

答案 2 :(得分:0)

据我所知,你的MVVM中有一个bool&#34; CanRemove&#34;。您可以使用.NET提供的BooleanToVisibilityConverter将其绑定到按钮可见性