2 votes

Comment partager une ressource entre les instances d'éléments ListBox ?

Nous avons une ListBox à rendu personnalisé qui maintient une instance d'un objet StreamGeometry basé sur sa largeur. Le contrôle doit ensuite partager cette instance StreamGeometry avec tous ses éléments à des fins de rendu.

Le seul moyen auquel nous pouvons penser est de mettre cette instance de StreamGeometry dans le ViewModel de la ListBox, puis de la lier à cette instance dans les DataTemplates individuels, ce qui me semble sale étant donné qu'il s'agit d'une chose réservée à la vue et qui ne devrait donc pas être dans le ViewModel du tout.

Remarque : nous pourrions également la stocker par le biais d'une propriété attachée à la ListBox (ou sous-classer la ListBox), mais nous nous retrouvons toujours avec une liaison de type "view-only", ce qui me semble inapproprié pour quelque chose comme ça.

Des idées ?

0voto

adabyron Points 4335

Vous pouvez faire du StreamGeometry une propriété de dépendance sur votre listview personnalisé, puis y faire référence par le biais de Binding MyGeometry, RelativeSource={RelativeSource AncestorType=ListView} .

De cette façon, il n'y a pas de ViewModel impliqué.

enter image description hereenter image description here

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:local="clr-namespace:WpfApplication1"
                xmlns:s="clr-namespace:System;assembly=mscorlib"
                Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <!-- default lsitviewitem style except for added path -->
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
            <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
            <Setter Property="Padding" Value="2,0,0,0"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListViewItem}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                            <StackPanel Orientation="Horizontal">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                <!-- added path-->
                                <Path Stretch="Uniform" Stroke="DarkBlue" Fill="DarkOrchid" Data="{Binding MyGeometry, RelativeSource={RelativeSource AncestorType=ListView}}" />
                            </StackPanel>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsSelected" Value="true"/>
                                    <Condition Property="Selector.IsSelectionActive" Value="false"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                            </MultiTrigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid >
        <local:CustomListView Margin="20" >
            <local:CustomListView.Items>
                <ListViewItem Content="ListViewItem1" />
                <ListViewItem Content="ListViewItem2" />
                <ListViewItem Content="ListViewItem3" />
            </local:CustomListView.Items>
        </local:CustomListView>
    </Grid>
</Window>

CustomListView :

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApplication1
{
    public class CustomListView : ListView
    {
        public StreamGeometry MyGeometry { get { return (StreamGeometry)GetValue(MyGeometryProperty); } set { SetValue(MyGeometryProperty, value); } }
        public static readonly DependencyProperty MyGeometryProperty = DependencyProperty.Register("MyGeometry", typeof(StreamGeometry), typeof(CustomListView), new PropertyMetadata(null));

        protected override void OnRender(DrawingContext drawingContext)
        {
            StreamGeometry geometry = new StreamGeometry(); // directly opening MyGeometry results in "must have isfrozen set to false to modify" error
            using (StreamGeometryContext context = geometry.Open()) 
            {
                Point p1 = new Point(this.ActualWidth * (2d / 5d), 0);
                Point p2 = new Point(this.ActualWidth / 2d, -10);
                Point p3 = new Point(this.ActualWidth * (3d / 5d), 0);

                context.BeginFigure(p1, true, true);

                List<Point> points = new List<Point>() { p2, p3 };
                context.PolyLineTo(points, true, true);
            }

            drawingContext.DrawGeometry(Brushes.DarkOrchid, new Pen(Brushes.DarkBlue, 1), geometry);

            this.MyGeometry = geometry;

            base.OnRender(drawingContext);
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X