2

我们有一个自定义渲染的 ListBox,它维护一个基于其宽度的 StreamGeometry 对象的实例。然后,该控件需要将该 StreamGeometry 实例与其所有项目共享以进行渲染。

我们能想到的唯一方法是将 StreamGeometry 实例放在 ListBox 的 ViewModel 中,然后在各个 DataTemplates 中绑定到它,考虑到这是一个仅限视图的东西,因此不应该在 ViewModel 中全部。

注意:我们也可以通过 ListBox(或 ListBox 的子类)上的附加属性来存储它,但我们仍然需要绑定一个仅查看的东西,这对我来说似乎是错误的。

有什么想法吗?

4

1 回答 1

0

您可以使 StreamGeometry 成为自定义列表视图上的依赖属性,然后通过Binding MyGeometry, RelativeSource={RelativeSource AncestorType=ListView}.

这样,不涉及 ViewModel。

在此处输入图像描述在此处输入图像描述

xml:

<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>

自定义列表视图:

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);
        }
    }
}
于 2013-03-17T13:05:18.767 回答