2016-09-22 109 views
-1

我发现了一些silimar问题,但这些并不完全是我需要的。 我想绑定stackpanel“IsEnabled”值来布尔“!IsIterrupted”值我的项目。这是我的XAML文件:WPF:双向数据绑定不起作用

<ListView ItemsSource="{Binding Path=Items}"> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <StackPanel IsEnabled="{Binding !IsInterrupted, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"> 
        <Button Command="{Binding Path=StopThreadCommand, Source={StaticResource viewModel}}" CommandParameter="{Binding Id}"/> 
       </StackPanel> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 

这是项目的样子:

public class ThreadDecorator : BaseThread , INotifyPropertyChanged 
{ 
    ... 
    public event PropertyChangedEventHandler PropertyChanged; 

    private bool _is_interrupted; 
    public bool IsInterrupted 
    { 
     get { return _is_interrupted; } 
     set 
     { 
      _is_interrupted = value; 
      OnPropertyChanged("IsInterrupted"); 
     } 
    } 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    ... 
} 

我的视图模型:

public class ThreadsViewModel : DependencyObject 
{ 

    private ThreadsModel _model; 
    public ThreadsModel Model 
    { 
     get { return _model; } 
     set 
     { 
      _model = value; 
     } 
    } 

    public ICollectionView Items 
    { 
     get { return (ICollectionView)GetValue(ItemsProperty); } 
     set { SetValue(ItemsProperty, value); } 
    } 

    public static readonly DependencyProperty ItemsProperty = 
     DependencyProperty.Register("Items", typeof(ICollectionView), typeof(ThreadsViewModel), new PropertyMetadata(null)); 

    public StopThreadCommand StopThreadCommand { get; set; } 

    public ThreadsViewModel() 
    { 
     this.Model = new ThreadsModel(); 
     Items = CollectionViewSource.GetDefaultView(Model.Threads); 
     this.StopThreadCommand = new StopThreadCommand(this); 
    } 

    public void InterruptThread(int id) 
    { 
     _model.InterruptThread(id); 
    } 
} 

StopThreadCommand:

public class StopThreadCommand : ICommand 
{ 
    public ThreadsViewModel ViewModel {get; set;} 
    public StopThreadCommand(ThreadsViewModel viewModel) 
    { 
     this.ViewModel = viewModel; 
    } 

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

    public void Execute(object parameter) 
    { 
     this.ViewModel.InterruptThread((int)parameter); 
    } 
} 

当我点击停止按钮IsInterrupted值从false更改为true,堆栈面板必须禁用,但UI不会更新。请帮助!

+0

什么是堆叠面板的数据上下文?执行此功能时是否看到任何绑定错误? – Versatile

+0

'!IsInterrupted'?你确定'!'会像你期望的那样工作吗? 'Binding.Path'不是一个任意的C#表达式。它是一个命名'DataContext'属性的字符串(或者它的一个属性的属性,如果'Foo.Bar')。 –

+0

下面是一些解决方案绑定到一个颠倒的布尔:实际上,一个人甚至写了一个'Binding'替换* * *让你否定布尔值:http:/ http://stackoverflow.com/a/1039681/424129。 /stackoverflow.com/a/27324780/424129 –

回答

1

默认属性Binding is Path,它是DataContext的属性/子属性的路径。这不是一个任意的C#表达式。所以你将Binding.Path设置为"!IsInterrupted"!IsInterrupted将不计算为IsInterrupted的布尔逆;它不会评估任何东西。它会让你这个调试输出流中:

System.Windows.Data Error: 40 : BindingExpression path error: '!IsInterrupted' property not found on 'object' 'ThreadDecorator' blah blah blah

<StackPanel 
    IsEnabled="{Binding !IsInterrupted, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"> 

一种方式做,这是write a boolean-inverse value converter(在that link另一端从克里斯·尼科尔的答案逐字被盗):

[ValueConversion(typeof(bool), typeof(bool))] 
public class InverseBooleanConverter: IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, Type targetType, object parameter, 
     System.Globalization.CultureInfo culture) 
    { 
     if (targetType != typeof(bool)) 
      throw new InvalidOperationException("The target must be a boolean"); 

     return !(bool)value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
     System.Globalization.CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 

    #endregion 
} 

用法:

<UserControl.Resources> 
    <local:InverseBooleanConverter x:Key="InverseBooleanConverter" /> 
</UserControl.Resources> 

<!-- stuff etc. --> 

IsEnabled="{Binding Path=IsReadOnly, Converter={StaticResource InverseBooleanConverter}}" 

你也可以写一个样式与DataTrigger,如果IsInterrupted为真,则将IsEnabled设置为False

+0

非常感谢!你解决了我的问题 –