2014-10-05 97 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 
    }