根据ListView填充启用/禁用WPF按钮

时间:2013-10-21 07:27:17

标签: c# visual-studio-2010 user-interface mvvm

我对MVVM完全不熟悉,所以请光临我,让我知道问题是否不够明确,我会添加更多信息。

我已使用以下代码在View AXML )中定义了一个按钮:

<Button Content="Fetch Data" Command="{Binding readInventoryFilesCommand}" CommandParameter="{Binding Path=Text, ElementName=browseFolderTextBox}" Name="button1" />

该按钮按预期工作,但如果已使用元素填充ListView,我希望启用/禁用该按钮。

  • 如果listView中没有元素 - &gt;按钮IsEnabled设置为false
  • 如果listView中有元素 - &gt;按钮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 

4 个答案:

答案 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);
 }