如何使列表项的一部分可选和其他不可选的WPF

时间:2019-05-22 08:04:07

标签: c# .net wpf

如何使列表项的一部分成为可选wpf,而其他项则不可选

我有一个列表视图,可以选择和取消选择其中的一个项目,并希望在按项目的一部分取消选择它时想要

用于在列表视图中选择和取消选择项目的类

public static class ListBoxSelectionBehavior
    {
        public static readonly DependencyProperty ClickSelectionProperty =
            DependencyProperty.RegisterAttached("ClickSelection",
                                                typeof(bool),
                                                typeof(ListBoxSelectionBehavior),
                                                new UIPropertyMetadata(false, OnClickSelectionChanged));

        public static bool GetClickSelection(DependencyObject obj)
        {
            return (bool)obj.GetValue(ClickSelectionProperty);
        }

        public static void SetClickSelection(DependencyObject obj, bool value)
        {
            obj.SetValue(ClickSelectionProperty, value);
        }

        private static void OnClickSelectionChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e)
        {
            ListView listBox = dpo as ListView;
            if (listBox != null)
            {
                if ((bool)e.NewValue == true)
                {
                    listBox.SelectionMode = SelectionMode.Multiple;
                    listBox.SelectionChanged += OnSelectionChanged;
                }
                else
                {
                    listBox.SelectionChanged -= OnSelectionChanged;
                }
            }
        }

        static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                ListView listBox = sender as ListView;
                var valid = e.AddedItems[0];
                foreach (var item in new ArrayList(listBox.SelectedItems))
                {
                    if (item != valid)
                    {
                        listBox.SelectedItems.Remove(item);
                    }
                }
            }
        }
    }

用于扩展包装面板的类,以添加说明和每个项目

    public class WrapPaneEx : WrapPanel
    {
        protected override Size ArrangeOverride(Size finalSize)
        {
            var size = base.ArrangeOverride(finalSize);

            foreach (UIElement fe in this.Children)
            {
                var itemLocation = GetItemLocation(fe);
                if (itemLocation == null)
                {
                    itemLocation = new ItemLocation(this, fe);
                    SetItemLocation(fe, itemLocation);
                }
                itemLocation.OnLocationPropertyChanged();
            }
            return size;
        }

        public static ItemLocation GetItemLocation(DependencyObject obj)
        {
            return (ItemLocation)obj.GetValue(ItemLocationProperty);
        }

        public static void SetItemLocation(DependencyObject obj, ItemLocation value)
        {
            obj.SetValue(ItemLocationProperty, value);
        }

        public static readonly DependencyProperty ItemLocationProperty = DependencyProperty.RegisterAttached("ItemLocation", typeof(ItemLocation), typeof(WrapPaneEx), new PropertyMetadata(null));
    }

    public class ItemLocation : INotifyPropertyChanged
    {
        public ItemLocation(Panel panel, UIElement itemContainer)
        {
            this._Panel = panel;
            this._ItemContainer = itemContainer;
        }

        private UIElement _ItemContainer;
        private Panel _Panel;

        public Point? Location
        {
            get
            {
                if (_Location == null && _Panel != null && _ItemContainer != null)
                {
                    _Location = _ItemContainer.TranslatePoint(default(Point), _Panel);
                }
                return _Location;
            }
        }
        private Point? _Location;

        public Point? LocationN
        {
            get
            {
                if (_LocationN == null && _Location == null && _Panel != null && _ItemContainer != null)
                {
                    Point? np = Location;
                    if (np != null)
                    {
                        _LocationN = new Point(-np.Value.X, -np.Value.Y);
                    }
                }
                return _LocationN;
            }
        }
        private Point? _LocationN;

        public event PropertyChangedEventHandler PropertyChanged;

        internal void OnLocationPropertyChanged()
        {
            _Location = null;
            _LocationN = null;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Location)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LocationN)));
        }
    }

当我在详细信息的画布上单击时,我希望在列表视图中取消选择项时无法选择

<ScrollViewer  x:Name="scollviewer" HorizontalAlignment="Stretch" >
                        <ListView x:Name="listview" Main:ListBoxSelectionBehavior.ClickSelection="True" HorizontalAlignment="Center" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedMovie}" PreviewMouseWheel="List_PreviewMouseWheel">
                                <ListView.Resources>
                                    <ControlTemplate TargetType="{x:Type ListViewItem}" x:Key="withDetailTemplate">
                                        <Grid>
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto"/>
                                                <RowDefinition Height="Auto"/>
                                            </Grid.RowDefinitions>
                                            <Border Grid.Row="0" x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="0" SnapsToDevicePixels="true">
                                                <Grid>
                                                    <local:MovieListItemControl/>
                                                    <Border Background="White" Visibility="Collapsed"
                                    Height="2" Grid.RowSpan="2" x:Name="indicator"
                                    VerticalAlignment="Bottom"/>
                                                </Grid>
                                            </Border>
                                            <!-- **************** -->
                                            <Canvas Grid.Row="1" x:Name="detailCanvas" 
                                                Width="0" selec
                                                Height="{Binding ElementName=detailGrid,Path=ActualHeight}"
                                                HorizontalAlignment="Left" VerticalAlignment="Top" Visibility="Collapsed">
                                                <Grid x:Name="detailGrid" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ScrollViewer},AncestorLevel=2},Path=ActualWidth}"
                                                   Canvas.Left="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListViewItem}},Path=(local:WrapPaneEx.ItemLocation).LocationN.X}">
                                                    <local:MovieDetailsControl/>
                                                </Grid>
                                            </Canvas>
                                            <!-- **************** -->
                                        </Grid>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsSelected" Value="true">
                                                <Setter Property="Background" TargetName="Bd" Value="Black"/>
                                                <Setter Property="Opacity" TargetName="Bd" Value="0.7"/>
                                                <Setter TargetName="indicator" Property="Visibility" Value="Visible"/>
                                                <Setter TargetName="detailCanvas" Property="Visibility" Value="Visible"/>

                                            </Trigger>
                                            <EventTrigger RoutedEvent="Loaded">
                                                <EventTrigger.Actions>
                                                    <BeginStoryboard>
                                                        <Storyboard>
                                                            <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1" />
                                                        </Storyboard>
                                                    </BeginStoryboard>
                                                </EventTrigger.Actions>
                                            </EventTrigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </ListView.Resources>
                                <ListView.ItemContainerStyle>
                                    <Style TargetType="{x:Type ListViewItem}">
                                        <Setter Property="Template" Value="{StaticResource withDetailTemplate}" />
                                    </Style>
                                </ListView.ItemContainerStyle>
                                <ListView.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <local:WrapPaneEx  HorizontalAlignment="Center" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ScrollViewer},AncestorLevel=2},Path=ActualWidth}"/>
                                    </ItemsPanelTemplate>
                                </ListView.ItemsPanel>
                            </ListView>
                    </ScrollViewer>

image for expected propgram

1 个答案:

答案 0 :(得分:0)

如果要将ListView中的某些元素设置为只读,则应使用IsHitTestVisible="False"上的ListViewIitem属性。从一个角度来看,可以为ListViewIem创建一种样式,然后使用DataTrigger将其打开和关闭。

<Style TargetType="ListViewItem">
    <Style.Triggers>
        <DataTrigger Binding="Property" Value="False">
            <Setter Property="IsHitTestVisible" Value="False"/>
        </DataTrigger>
    </Style.Triggers>
</Style>  

因为这是DependencyProperty,所以您也可以直接绑定到该媒体资源:

<Style TargetType="ListViewItem">
    <Setter Property="IsHitTestVisible" Value="{Binding Property}"/>
</Style>

MSDN说明。
这里是简要说明:

  

获取或设置一个值,该值声明此元素是否可能从其呈现的内容的某些部分作为命中测试结果返回。这是一个依赖属性。