2011-07-06 26 views
6

MVVM, VS 2008 ve .NET 3.5 SP1 kullanıyorum. Her biri bir IsSelected özelliğini sergileyen öğelerin bir listesi var. Listedeki tüm öğelerin seçimini/seçimini (her öğenin IsSelected özelliğini güncelleştirerek) yönetmek için bir CheckBox ekledim. PropertyChanged olay CheckBox'un sınır denetimi için çalışırken IsChecked özelliği görünümde güncelleştiriliyor dışında her şey çalışıyor.WPF CheckBox Bağlamam neden çalışmıyor?

<CheckBox 
    Command="{Binding SelectAllCommand}" 
    IsChecked="{Binding Path=AreAllSelected, Mode=OneWay}" 
    Content="Select/deselect all identified duplicates" 
    IsThreeState="True" /> 

Benim VM:

public class MainViewModel : BaseViewModel 
{ 
    public MainViewModel(ListViewModel listVM) 
    { 
    ListVM = listVM; 
    ListVM.PropertyChanged += OnListVmChanged; 
    } 

    public ListViewModel ListVM { get; private set; } 
    public ICommand SelectAllCommand { get { return ListVM.SelectAllCommand; } } 

    public bool? AreAllSelected 
    { 
    get 
    { 
     if (ListVM == null) 
     return false; 

     return ListVM.AreAllSelected; 
    } 
    } 

    private void OnListVmChanged(object sender, PropertyChangedEventArgs e) 
    { 
    if (e.PropertyName == "AreAllSelected") 
     OnPropertyChanged("AreAllSelected"); 
    } 
} 

Burada SelectAllCommand veya bireysel öğe seçimi uygulanmasını gösteren değilim ama alakalı görünmüyor. Kullanıcı listedeki tek bir öğeyi seçtiğinde (veya tüm öğeleri seçmek/devre dışı bırakmak için CheckBox'ı tıklattığında), OnPropertyChanged ("AreAllSelected") kod satırının yürütüldüğünü ve hata ayıklayıcısında izlendiğini doğrulayabilirim. PropertyChanged olayı beklendiği gibi abone olur ve bekler. Ancak AreAllSelected özelliğinin getiri, yalnızca görüntü bir kez oluşturulduğunda gerçekleştirilir. Visual Studio'nun Çıktı penceresi herhangi bir veri bağlama hatası bildirmiyor, bu yüzden ne söyleyebilirim, CheckBox'ın IsSelected özelliği düzgün bir şekilde bağlı.

Bir Button ile CheckBox değiştirin:

<Button Content="{Binding SelectAllText}" Command="{Binding SelectAllCommand}"/> 

ve VM güncelleme:

... 

public string SelectAllText 
{ 
    get 
    { 
    var msg = "Select All"; 
    if (ListVM != null && ListVM.AreAllSelected != null && ListVM.AreAllSelected.Value) 
     msg = "Deselect All"; 

    return msg; 
    } 
} 

... 

private void OnListVmChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "AreAllSelected") 
    OnPropertyChanged("SelectAllText"); 
} 

her şey beklendiği gibi çalışır - tüm öğelerin seçildiğinden olarak düğmenin metin desected/güncellenir. CheckBox'ın IsSelected özelliği üzerindeki Bağlama ile ilgili eksik olan bir şey var mı?

Yardımlarınız için teşekkürler!

cevap

5

Sorunu buldum. WPF 3.0'da, IsChecked'deki OneWay bağlamaları olan bir bağın varlığının kaldırılmasına neden oluyor gibi görünüyor. Yardım için this post sayesinde, bu hata WPF 4.0

'da yeniden üretildi gibi üretildi Yeniden üretmek için yeni bir WPF projesi oluşturun.

using System; 
using System.ComponentModel; 
using System.Windows.Input; 

namespace Foo 
{ 
    public class FooViewModel : INotifyPropertyChanged 
    { 
    private bool? _isCheckedState = true; 

    public FooViewModel() 
    { 
     ChangeStateCommand = new MyCmd(ChangeState); 
    } 

    public bool? IsCheckedState 
    { 
     get { return _isCheckedState; } 
    } 

    public ICommand ChangeStateCommand { get; private set; } 

    private void ChangeState() 
    { 
     switch (_isCheckedState) 
     { 
     case null: 
      _isCheckedState = true; 
      break; 
     default: 
      _isCheckedState = null; 
      break; 
     } 

     OnPropertyChanged("IsCheckedState"); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string propertyName) 
    { 
     var changed = PropertyChanged; 
     if (changed != null) 
     changed(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    } 

    public class MyCmd : ICommand 
    { 
    private readonly Action _execute; 
    public event EventHandler CanExecuteChanged; 

    public MyCmd(Action execute) 
    { 
     _execute = execute; 
    } 

    public void Execute(object parameter) 
    { 
     _execute(); 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 
    } 
} 

Değiştir Window1.xaml.cs:

using System.Windows; 
using System.Windows.Controls.Primitives; 

namespace Foo 
{ 
    public partial class Window1 
    { 
    public Window1() 
    { 
     InitializeComponent(); 
    } 

    private void OnClick(object sender, RoutedEventArgs e) 
    { 
     var bindingExpression = MyCheckBox.GetBindingExpression(ToggleButton.IsCheckedProperty); 
     if (bindingExpression == null) 
     MessageBox.Show("IsChecked property is not bound!"); 
    } 
    } 
} 

Değiştir Window1.xaml: butonuna

<Window 
    x:Class="Foo.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:Foo" 
    Title="Window1" 
    Height="200" 
    Width="200" 
    > 

    <Window.DataContext> 
    <vm:FooViewModel /> 
    </Window.DataContext> 

    <StackPanel> 
    <CheckBox 
     x:Name="MyCheckBox" 
     Command="{Binding ChangeStateCommand}" 
     IsChecked="{Binding Path=IsCheckedState, Mode=OneWay}" 
     Content="Foo" 
     IsThreeState="True" 
     Click="OnClick"/> 
    <Button Command="{Binding ChangeStateCommand}" Click="OnClick" Content="Change State"/> 
    </StackPanel> 
</Window> 

tıklayın birkaç kez

bir FooViewModel.cs ekle ve CheckBox durumunun gerçek ve null (false değil) arasında geçişini görün. Ancak CheckBox'a tıklayın ve Bağlamanın IsChecked özelliğinden kaldırıldığını göreceksiniz.

geçici çözüm:

Güncelleme IsChecked TwoWay olmaya bağlayıcı ve açık olma UpdateSourceTrigger ayarlayın: artık salt okunur oluyor böylece

IsChecked="{Binding Path=IsCheckedState, Mode=TwoWay, UpdateSourceTrigger=Explicit}" 

ve bağlı özelliğini güncelleyin:

public bool? IsCheckedState 
{ 
    get { return _isCheckedState; } 
    set { } 
} 
İlgili konular