2014-10-05 98 views
0

在我的列表框中,我有控件需要绑定到我的ItemsSource以及ViewModel中的属性。你可以看到这些按钮需要做到这两点。我似乎能够做到这一点的唯一方法是非常难看的(请参阅IsEnabled属性绑定到视图的视图模型)。我想知道做这件事的最好方法是什么。WPF DataBinding与ItemsSource的交互

编辑:澄清我想要将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(); 
    } 
} 

回答

1

你并不需要在所有转换器时,你可以直接使用RelativeSource标记扩展访问视图模型。这应该工作:

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

由于ListBox的DataContext指向viewModel实例,以上发布的代码将工作。

+1

谢谢你,这是我正在寻找。有意义,有效。 – 2014-10-05 18:46:29

+0

但是,当您执行MVVM时,这不是您应该去的方式。一个按钮应该有一个命令绑定 – blindmeis 2014-10-06 06:19:08

1

当你做mvvm并想使用按钮时,你应该使用DelegateCommand或RelayCommand。如果你使用这个,那么你只需要正确地实现ICommand(CanExecute!),绑定到该按钮的Command将为你处理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 
    }