【问题标题】:Prevent Listbox selection防止列表框选择
【发布时间】:2019-12-04 08:03:09
【问题描述】:

我有一个多选列表框,其中只允许选择某些项目组合。 如何拒绝某些选择? 列表框绑定到视图模型。我以为我可以在属性设置器中做到这一点,但它不起作用。

XAML

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedItems" Value="{Binding Path=SelectedItems, ElementName=TranslatorsListView}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

在视图模型中

public System.Collections.IList SelectedItems 
{
    get
    {
        return SelectedModels;
    }
    set 
    { 
        //what here?
    }
}  

编辑: 我应该说清楚,我正在使用多选。这就是我使用交互触发器而不只是绑定到 SelectedItem 的原因。链接的答案是单选。

【问题讨论】:

标签: c# wpf mvvm listbox


【解决方案1】:

我发现最简单的方法是不使用 SelectionMode 或 SelectedItem,而是使用 Tapped 事件。从这里你可以得到“选定的项目”。

然后,我在 ViewModel 中设置一个绑定属性,如果我想选择它,View 将使用该属性更改 ListView 中所选项目的背景。要有效地做到这一点,您的 ListView 需要绑定到 ViewModels 的 ObservableCollection(或实现 INotifyPropertyChanged 的​​类)。

这里有一些粗略的代码来说明我的意思: 在 Xaml 查看代码

<ListView 
    ItemsSource ="{Binding Values}"
    ItemTapped="OnItemTapped"
    HasUnevenRows="True"
    RefreshAllowed="True"
    SelectionMode="None"
    >
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid  RowSpacing="0" >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100*"/>
                        <ColumnDefinition Width="40"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30*"/>
                    </Grid.RowDefinitions>
                    <BoxView Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" BackgroundColor="{StaticResource Blue}" IsVisible="{Binding IsSelected}" />
                    <Label   Grid.Column="0" Grid.Row="0" HorizontalTextAlignment="Center" VerticalOptions="Center" Text="{Binding Destination}"/>
                    <Label   Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Start" VerticalOptions="Center" Text="{Binding Value}"/>
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

在后面的代码中:

private void OnItemTapped(object sender, ItemTappedEventArgs e)
{
    var param = (ValueViewModel)e.Item;
    if (((SourceViewModel)BindingContext).SelectValueCommand.CanExecute(param))
    {
        ((SourceViewModel)BindingContext).SelectValueCommand.Execute(param);
    }
}

然后使用这些类——第一个是视图的BindingContext

public class SourceViewModel:INotifyPropertyChanged
{
    public SourceViewModel (List<ValueViewModel> list)
    {
        SelectValueCommand = new Command<ValueViewModel>((value) => ExecuteSelectValueCommand(value), (value)=>!IsBusy);
    }

    private ObservableCollection<ValueViewModel> _values = new ObservableCollection<ValueViewModel>();
    private bool _isSelected;
    private sring _description;

    public ICommand SelectValueCommand;
    public bool IsBusy{get;set;}

    public ObservableCollection<ValueViewModel> Values 
    {
        get=>_values;
        set
        {
            _values = value;
            OnPropertyChanged(nameof(Values));
        }
    }

    public void ExecuteSelectValueCommand(ValueViewModel value)
    {
        if(IsBusy) return;

        item.IsSelected = CanValueBeSelected(value);        
    }

    private bool CanValueBeSelected(ValueViewModel value)
    {
        var result = false;

        //Some logic to determine if it can be selected

        return result;
    }
    #region INotifyPropertyChanged implementation
    // ...
    #endregion  
}


public class ValueViewModel:INotifyPropertyChanged
{
    public ValueViewModel (string description, int value)
    {
        Description = description;
        Value = value;
    }

    private int _value;
    private bool _isSelected;
    private sring _description;

    public int Value
    {
        get=>_value;
        set
        {
            _value=value;
            OnPropertyChanged(nameof(Value));
        }
    }

    public bool IsSelected
    {
        get=> _isSelected;
        set
        {
            _isSelected= value;
            OnPropertyChanged(nameof(IsSelected));
        }
    }

    public string Description
    {
        get=> _description;
        set
        {
            _description= value;
            OnPropertyChanged(nameof(Description));
        }
    }
    #region INotifyPropertyChanged implementation
    // ...
    #endregion  
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    相关资源
    最近更新 更多