как сделать часть элемента списка доступной для выбора 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>
@vsarunov я добавляю туда код
Это одна и та же часть для выбора и отмены выбора? Например, флажок или переключатель? Который вы могли бы превратить во что-то похожее на что-то другое. Сделайте все остальные тесты на попадание видимыми ложными. И является фокусируемым ложным, поэтому вы не можете использовать стрелку или вкладку для него.
это не работает для focussable, я пробовал
Вы пробовали вместо этого использовать IsHitTestVisible = "False"
?
Если вы хотите, чтобы некоторые элементы в вашем 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 объяснение.
И вот краткое объяснение:
Gets or sets a value that declares whether this element can possibly be returned as a hit test result from some portion of its rendered content. This is a dependency property.
Не могли бы вы привести пример кода того, что у вас есть прямо сейчас? Что вы пробовали и т.д.? Какие типы объектов находятся внутри listView?