Есть ли общий способ установить DataContext ItemContainer под мышью для свойства какого-либо другого элемента управления? - PullRequest
3 голосов
/ 08 августа 2010

При наведении указателя мыши на элемент в списке, как я могу установить свойство для другого элемента в DataContext элемента списка?

Я пытаюсь создать область, в которой я могу отобразить предварительный просмотр элемента, который в данный момент находится под курсором мыши. Я могу сделать это, используя программный код, но я хотел бы найти альтернативный способ, который мог бы использовать EventSetters / Binding / Triggers / AttachedProperties или любые другие средства.

Цель состоит в том, чтобы применить решение в более слабосвязанном сценарии, где элемент управления ListView может находиться в отдельном файле ресурсов, а элемент управления PreviewControl может совместно использоваться несколькими объектами ListView для отображения предварительных просмотров различных типов.

Следующий фрагмент кода работает, но требует кода позади:

<Window x:Class="Previewer.PreviewWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="PreviewWindow" Height="300" Width="300">
<Window.Resources>
    <x:Array x:Key="Data" Type="sys:String">
        <sys:String>First</sys:String>
        <sys:String>Second</sys:String>
    </x:Array>

    <CollectionViewSource x:Key="DataSource" Source="{StaticResource Data}"/>
</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <ContentControl Grid.Row="0" x:Name="PreviewControl"/>

    <ListView Grid.Row="1" ItemsSource="{Binding Source={StaticResource DataSource}}">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <EventSetter Event="MouseEnter" Handler="ListViewItem_MouseEnter"/>
                <EventSetter Event="MouseLeave" Handler="ListViewItem_MouseLeave"/>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</Grid>

Код, который в данный момент делает свое дело:

public partial class PreviewWindow : Window
{
    public PreviewWindow()
    {
        InitializeComponent();
    }

    private void ListViewItem_MouseEnter(object sender, MouseEventArgs e)
    {
        var listViewItem = (ListViewItem)sender;
        PreviewControl.Content= listViewItem.DataContext;
    }

    private void ListViewItem_MouseLeave(object sender, MouseEventArgs e)
    {
        var listViewItem = (ListViewItem)sender;
        PreviewControl.Content= null;
    }
}

1 Ответ

1 голос
/ 11 августа 2010

Решение 1 (не такое общее, но простое и работает):

инкапсулирует логику, которую вы уже реализовали, в пользовательский элемент управления, который имеет новое свойство зависимостей (typeof (объект)), которое представляет HoveredItemContext. В конструкторе своего пользовательского представления списка вы можете создать ContainerStyle и прикрепить события. Установите HoveredItemContext в этом EventHandlers, и вы можете привязать это свойство извне:

 <ContentControl Grid.Row="0" x:Name="PreviewControl" 
     Content="{Binding ElementName=MyListView, Path=HoveredItemContext}"/>
 <local:MyListView Grid.Row="1" x:Name="MyListView" 
     ItemsSource="{Binding Source={StaticResource DataSource}}" />

А вот и пользовательский элемент управления (работает):

public class MyListView : ListView
{
    public static readonly DependencyProperty HoveredItemContextProperty = DependencyProperty.Register(
        "HoveredItemContext",
        typeof(object),
        typeof(MyListView),
        new PropertyMetadata(null));

    public object HoveredItemContext
    {
        get { return GetValue(HoveredItemContextProperty); }
        set { SetValue(HoveredItemContextProperty, value); }
    }

    public MyListView()
    {
        this.ItemContainerStyle = new Style()
        {
            TargetType = typeof(ListViewItem),
        };

        this.ItemContainerStyle.Setters.Add(new EventSetter(ListViewItem.MouseEnterEvent,
            (MouseEventHandler)((s, e) =>
            {
                this.HoveredItemContext = (s as ListViewItem).DataContext;
            })));

        this.ItemContainerStyle.Setters.Add(new EventSetter(ListViewItem.MouseLeaveEvent,
            (MouseEventHandler)((s, e) =>
            {
                this.HoveredItemContext = null;
            })));
    }
}

Решение 2 (более общее):

Я все еще работаю над ней над аналогичной проблемой, но она еще не закончена;) Если я ее закончу, я опубликую это здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...