我对MVVM
完全不熟悉,所以请光临我,让我知道问题是否不够明确,我会添加更多信息。
我已使用以下代码在View
( AXML )中定义了一个按钮:
<Button Content="Fetch Data" Command="{Binding readInventoryFilesCommand}" CommandParameter="{Binding Path=Text, ElementName=browseFolderTextBox}" Name="button1" />
该按钮按预期工作,但如果已使用元素填充ListView
,我希望启用/禁用该按钮。
IsEnabled
设置为false
IsEnabled
设置为true
我尝试使用IsEnabled="{Binding ...
,但我没有在code completion
中获得Visual Studio C# Express
,而且很难猜测替代方案。
命令如下所示:
internal class ReadInventoryFilesCommand : ICommand
{
public ReadInventoryFilesCommand(ResourceViewModel viewModel)
{
_viewModel = viewModel;
}
private ResourceViewModel _viewModel;
#region ICommand Members
event EventHandler ICommand.CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
bool ICommand.CanExecute(object parameter)
{
return _viewModel.CanUpdate;
}
void ICommand.Execute(object parameter)
{
_viewModel.ReadInventroyFiles(parameter.ToString());
}
#endregion
}
修改 的 这是Bobs建议之后的当前代码:
internal class ReadInventoryFilesCommand : ICommand
{
public ReadInventoryFilesCommand(ResourceViewModel viewModel)
{
_viewModel = viewModel;
_viewModel.PropertyChanged+= (s,e) => {
if (e.PropertyName == "CanUpdate") RaiseCanExecuteChanged();
};
}
private ResourceViewModel _viewModel;
event EventHandler ICommand.CanExecuteChanged;
bool ICommand.CanExecute(object parameter)
{
return _viewModel.CanUpdate;
}
void ICommand.Execute(object parameter)
{
_viewModel.ReadInventroyFiles(parameter.ToString());
}
void RaiseCanExecuteChanged() {
var handler = this.CanExecuteChanged;
if (handler != null) handler(this,EventArgs.Empty);
}
}
它会产生以下错误:
An explicit interface implementation of an event must use event accessor syntax
答案 0 :(得分:2)
您需要在命令执行时引发CanExecuteChanged事件。
修改强>
正如gehho在评论中提到的那样,在使用ICommand接口时,您不需要绑定到IsEnabled属性,因为Button将使用CanExecute
函数来确定它是否已启用。
但是,您需要引发CanExecuteChanged
事件以通知命令值已更改。
结束编辑
假设_viewModel
实现INotifyPropertyChanged
,您可以在viewmodel更改时挂钩并在命令上引发更改的事件:
我提供了两个版本,一个使用ICommand的显式实现,另一个只是实现没有显式ICommand前缀的属性和方法。两者都应该有效。我通常会使用版本2,除非有特定要求的方法存在冲突。
编辑版本1 - 明确实施
internal class ReadInventoryFilesCommand : ICommand
{
public ReadInventoryFilesCommand(ResourceViewModel viewModel)
{
_viewModel = viewModel;
_viewModel.PropertyChanged+= (s,e) => {
if (e.PropertyName == "CanUpdate") RaiseCanExecuteChanged();
};
}
event EventHandler ICommand.CanExecuteChanged { add; remove; }
private ResourceViewModel _viewModel;
bool ICommand.CanExecute(object parameter)
{
return _viewModel.CanUpdate;
}
void ICommand.Execute(object parameter)
{
_viewModel.ReadInventroyFiles(parameter.ToString());
}
void RaiseCanExecuteChanged() {
var handler = ((ICommand)this).CanExecuteChanged;
if (handler != null) handler(this,EventArgs.Empty);
}
}
编辑版本2
internal class ReadInventoryFilesCommand : ICommand
{
public ReadInventoryFilesCommand(ResourceViewModel viewModel)
{
_viewModel = viewModel;
_viewModel.PropertyChanged+= (s,e) => {
if (e.PropertyName == "CanUpdate") RaiseCanExecuteChanged();
};
}
public event EventHandler CanExecuteChanged;
private ResourceViewModel _viewModel;
public bool CanExecute(object parameter)
{
return _viewModel.CanUpdate;
}
public void Execute(object parameter)
{
_viewModel.ReadInventroyFiles(parameter.ToString());
}
void RaiseCanExecuteChanged() {
var handler = this.CanExecuteChanged;
if (handler != null) handler(this,EventArgs.Empty);
}
}
答案 1 :(得分:1)
我认为你可以使用绑定转换器: 代码Windows1.xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
xmlns:converters="clr-namespace:WpfApplication1"
>
<Window.Resources>
<converters:CoverterItemsSource2Enabled x:Key="converter" />
</Window.Resources>
<Grid Margin="0,0,-256,0">
<ListView x:Name="listView" HorizontalAlignment="Left" Margin="10,10,0,10" VerticalAlignment="Stretch" Width="196">
<ListView.View>
<GridView>
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
<Button Content="Button" HorizontalAlignment="Left" Margin="211,10,0,0" VerticalAlignment="Top" IsEnabled="{Binding Path=Items, ElementName=listView, Converter={StaticResource converter} }" Width="75"/>
</Grid>
</Window>
代码转换器:
namespace WpfApplication1
{
class CoverterItemsSource2Enabled : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return false;
if(value is ItemCollection)
{
if ((value as ItemCollection).Count > 0)
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
答案 2 :(得分:1)
这是将IsEnabled
绑定到Items.Count
时的默认行为。
例如
<ListView x:Name="RulesList" />
<Button IsEnabled="{Binding Items.Count, ElementName=RulesList}" />
在此示例中Button
将在ListView
没有项目时被禁用,并且当它有一个或多个项目时将被启用。
答案 3 :(得分:0)
你在谈论这个吗?:
private void ListView1_SourceUpdated(object sender, DataTransferEventArgs e)
{
Button1.IsEnabled==(ListView1.Items.Count>0);
}