如何禁止选择交互式ListBox项?

时间:2012-11-26 15:21:12

标签: c# wpf button listbox

我的ListBox中的一些项目使用包含按钮和TextBox的模板。如何才能使其无法从列表中选择这些项目,但仍然可以与按钮相互作用?

编辑:

我仍然需要能够选择此列表中的其他项目,而不是具有此模板的项目。

2 个答案:

答案 0 :(得分:1)

使用ItemsControl代替ListBox

答案 1 :(得分:1)

我们可以使用附加属性到ListBoxItem(在我实现之后找到someone who had done almost the same):

public class ListBoxItemEx
{
    public static bool GetCanSelect(DependencyObject obj)
    {
        return (bool)obj.GetValue(CanSelectProperty);
    }
    public static void SetCanSelect(DependencyObject obj, bool value)
    {
        obj.SetValue(CanSelectProperty, value);
    }
    public static readonly DependencyProperty CanSelectProperty =
        DependencyProperty.RegisterAttached("CanSelect", typeof(bool), typeof(ListBoxItemEx), new UIPropertyMetadata(true, OnCanSelectChanged));

    private static void OnCanSelectChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        var item = sender as ListBoxItem;
        if (item == null)
            return;

        if ((bool)args.NewValue)
        {
            item.Selected -= ListBoxItemSelected;
        }
        else
        {
            item.Selected += ListBoxItemSelected;
            item.IsSelected = false;
        }
    }

    private static void ListBoxItemSelected(object sender, RoutedEventArgs e)
    {
        var item = sender as ListBoxItem;
        if (item == null)
            return;
        item.IsSelected = false;
    }
}

xaml:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow"
    Width="525"
    Height="350">
<Window.Resources>
    <Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="local:ListBoxItemEx.CanSelect" Value="{Binding CanSelect}"/>
    </Style>
</Window.Resources>     
<Window.DataContext>
    <local:ViewModel />
</Window.DataContext>
<Grid Name="LayoutRoot">
    <ListBox ItemsSource="{Binding Elements}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}" SelectionMode="Multiple" />
</Grid>

viewmodel:

public class ViewModel : INotifyPropertyChanged
{
    #region INotifyPropertyChanged values

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion


    public List<Dummy> Elements { get; set; }

    public ViewModel()
    {
        this.Elements = new List<Dummy>(){
            new Dummy() { CanSelect =true, MyProperty = "Element1"},
            new Dummy() { CanSelect =false, MyProperty = "Element2"},
            new Dummy() { CanSelect =true, MyProperty = "Element3"},
            new Dummy() { CanSelect =false, MyProperty = "Element4"},
            new Dummy() { CanSelect =true, MyProperty = "Element5"},
            new Dummy() { CanSelect =true, MyProperty = "Element6"},
            new Dummy() { CanSelect =true, MyProperty = "Element7"},
            new Dummy() { CanSelect =true, MyProperty = "Element8"},
            new Dummy() { CanSelect =false, MyProperty = "Element9"},
        };
    }
}

public class Dummy
{
    public bool CanSelect { get; set; }

    public string MyProperty { get; set; }

    public override string ToString()
    {
        return this.MyProperty;
    }
}

这种方法唯一需要注意的是,如果ListBox具有单个选择,则尝试选择一个不可选择的项目将取消选择当前选定的项目,或者如果ListBox具有扩展选择,则取消选择all。