我发现了一些silimar问题,但这些并不是我所需要的。 我想将stackpanel“IsEnabled”值绑定到我的项目的bool“!IsIterrupted”值。这是我的XAML文件:
<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));
}
}
...
}
我的ViewModel:
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,并且必须禁用stackpanel,但UI不会更新。求救!
答案 0 :(得分:1)
Binding
is Path
的默认属性,它是DataContext
的属性/子属性的路径。它不是一个任意的C#表达式。因此,您要将Binding.Path
设置为"!IsInterrupted"
。 !IsInterrupted
不会评估IsInterrupted
的布尔逆;它不会评估任何东西。它会在调试输出流中找到你:
System.Windows.Data错误:40:BindingExpression路径错误:&#39;!IsInterrupted&#39;在&#39; object&#39;上找不到的属性&#39; ThreadDecorator&#39; blah blah blah
<StackPanel
IsEnabled="{Binding !IsInterrupted, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
这样做的一种方法是write a boolean-inverse value converter(来自Chris Nicol的逐字逐句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
为真,您还可以使用IsEnabled
来编写样式,将False
设置为IsInterrupted
。