【发布时间】:2014-06-22 10:14:49
【问题描述】:
我有一个简单的按钮:
<Button Content="Print" Command="{Binding PrintCommand}"/>
...用命令:
private RelayCommand _printCommand;
public ICommand PrintCommand
{
get
{
if (_printCommand == null)
{
_printCommand = new RelayCommand(param => Print(),
() => (Files != null && Files.Count > 0));
}
return _printCommand;
}
}
仅当Files 集合不为空或其中包含某些项目时才启用。以下是合集:
private ObservableCollection<RecordModel> _files;
public ObservableCollection<RecordModel> Files
{
get { return _files; }
set
{
if (_files == value)
{
return;
}
_files = value;
OnPropertyChanged("Files");
}
}
集合绑定到窗口中的ListView。到目前为止,没有什么特别的……这就是奇怪的行为出现的地方……
如果我在集合中有足够的项目来显示ListView 的ScrollBar,那么我的按钮将显示为Enabled,这很好。如果我没有物品,那就是Disabled,这也不错。但是,如果我有足够的项目来填充可见ListView 的一部分,而不会触发ScrollBar 的出现,那么我的按钮将显示为Disabled。如果我专注于任何控件,包括按钮本身,那么它会弹出为Enabled。我不知道发生了什么事。起初,我以为它可能是我正在使用的按钮模板,所以我去掉了它并保留了默认设置的按钮,但奇怪的行为仍然存在。
有什么想法吗?
这是RelayCommand 类。我不确定其中是否存在问题,但这就是我一直在使用的:
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Func<bool> _canExecute;
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Func<bool> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
编辑:
这就是我如何填充我的收藏。
public FileManagerViewModel()
{
LoadCollection();
}
private void LoadCollection()
{
Task task = new Task(() =>
{
Files = DbWorker.GetFiles();
});
task.Start();
}
以下是我如何将集合绑定到ListView:
<Window.DataContext>
<vm:FileManagerViewModel/>
</Window.DataContext>
<Window.Resources>
<CollectionViewSource Source="{Binding Files}" x:Key="GroupedFiles">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="RepNum"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<ListView ItemsSource="{Binding Source={StaticResource GroupedFiles}}">
...
</ListView
编辑:
嗯,我不知道这是否是它或者它是如何导致它的(尤其是在整个 ScrollBar 情况下),但是当我不使用 Task 来更新我的收藏时,我不会不会遇到这种行为。当然,我必须处理由于冗长的操作而导致的挂起。考虑到我不想阻塞 UI 线程,不知道如何解决这个问题。我什至试过这个,它没有改变任何东西:
var temp = new ObservableCollection<RecordModel>();
Task task = new Task(() =>
{
temp = DbWorker.GetFiles();
});
task.ContinueWith((result) =>
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
Files = temp;
}));
});
task.Start();
但我没有看到属性未更新的问题。我已经检查并根据需要更新所有属性。这只是CanExecute 的状态更新中的一点挂起,仅通过焦点更改(在这种情况下)进行更新。
就我所知,似乎线程和命令之间存在问题......嗯。每次我通过单击手动为 UI 元素赋予焦点时,命令都会更新(或者它会出现)。如果 ScrollBar 出现或消失,也会发生这种情况。但随后其他 UI 元素不执行任何操作,例如文本。
【问题讨论】:
-
我知道这可能是什么。您能否发布相关的 XAML 并展示您创建视图模型的方式/位置以及设置 Files 属性的位置/方式?
-
@MichaelGunter XAML 的哪一部分?有很多,所以我不想充斥着代码。我发布了 ViewModel 部分,显示了我如何设置我的收藏。你有什么样的想法?
-
您能否也发布将 IsEnabled 属性为您的按钮绑定到集合大小的 xaml 部分。
-
@ankhuri 启用/禁用由命令处理。该代码已发布。