Векторное изображение как многоразовый фрагмент XAML - PullRequest
9 голосов
/ 08 декабря 2010

Я хочу повторно использовать некоторый фрагмент XAML как изображение в некотором приложении / библиотеке WPF.

История проблемы следующая:

Легко повторно использовать растровое изображение в приложении WPF. Изображение может быть добавлено в качестве ресурса, я могу использовать <Image Source="packURI"/> во многих местах в XAML, поэтому изображение будет таким же.

Но я бы хотел иметь возможность сделать то же самое для векторного изображения. Само изображение может быть представлено как Path, но я не могу повторно использовать тот же Path в качестве ресурса, потому что использование его в нескольких разных местах (и, возможно, из нескольких потоков пользовательского интерфейса) запрещено (элемент пользовательского интерфейса может иметь только один родитель).

Более того, вопрос усложняется, если я хочу построить «образ» из нескольких Path с, используйте для него Canvas. Или какой-нибудь произвольный код XAML.

Я попытался использовать Style для Path, поэтому изображение представляется следующим образом:

<Path Style={StaticResource VectorImage1}/>

Это, похоже, способ многократного использования, но меня беспокоят две проблемы:

  1. Если реализация векторного изображения изменяется с Path на (например) Canvas, мне нужно будет заменить его не только в стиле, но и везде в исходном коде, который его использует.
  2. Определение пути с использованием стиля представляется слишком многословным.
  3. Я не вижу возможности обобщить этот подход для использования Canvas или произвольного кода XAML.
  4. Синтаксис кажется довольно неестественным.

Существует другой способ получить повторно используемый фрагмент XAML, через определение UserControl, но определение отдельного пользовательского элемента управления для каждого векторного изображения представляется излишним.

Есть ли лучший, хороший, правильный способ определения многократно используемого фрагмента XAML?

Ответы [ 3 ]

15 голосов
/ 08 декабря 2010

Вы можете добавить атрибут x: Shared в ресурс ресурса и использовать его в качестве статического ресурса.Это будет работать, если «MyVectorImage» изменится на что-то еще

Обновление
Возможно, лучше использовать ContentControl или аналогичный, чтобы иметь возможность добавлять свойства, такие как Margin и т. Д.

<Window.Resources>
    <Path x:Key="MyVectorImage"
          x:Shared="False"
          Stroke="DarkGoldenRod"
          StrokeThickness="3"
          Data="M 10,20 C 10,25 40,35 40,17 H 28"
          Stretch="Fill"
          Width="100"
          Height="40"/>
</Window.Resources>
<StackPanel>
    <ContentControl Margin="10" Content="{StaticResource MyVectorImage}"/>
    <ContentControl Margin="10" Content="{StaticResource MyVectorImage}"/>
</StackPanel>

Пример.Вы заменяете «MyVectorImage» на StackPanel, содержащую два пути.

<Window.Resources>
    <StackPanel x:Key="MyVectorImage"
                x:Shared="False">
        <Path Stroke="DarkGoldenRod"
              StrokeThickness="3"
              Data="M 10,20 C 10,25 40,35 40,17 H 28"
              Stretch="Fill"
              Width="100"
              Height="40"/>
        <Path Stroke="DarkGoldenRod"
              StrokeThickness="3"
              Data="M 10,20 C 10,25 40,35 40,17 H 28"
              Stretch="Fill"
              Width="100"
              Height="40"/>
    </StackPanel>
</Window.Resources>
5 голосов
/ 09 декабря 2010

После некоторых исследований есть еще один вариант: использовать DrawingImage в качестве Source для изображения. Обычный источник изображения - BitmapSource, однако это может быть и «векторная графика».

Вот пример :

<Image>
  <Image.Source>
    <DrawingImage PresentationOptions:Freeze="True">
      <DrawingImage.Drawing>
        <GeometryDrawing>
          <GeometryDrawing.Geometry>
            <GeometryGroup>
              <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
              <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
            </GeometryGroup>
          </GeometryDrawing.Geometry>
          <GeometryDrawing.Brush>
            <LinearGradientBrush>
              <GradientStop Offset="0.0" Color="Blue" />
              <GradientStop Offset="1.0" Color="#CCCCFF" />
            </LinearGradientBrush>
          </GeometryDrawing.Brush>
          <GeometryDrawing.Pen>
            <Pen Thickness="10" Brush="Black" />
          </GeometryDrawing.Pen>
        </GeometryDrawing>
      </DrawingImage.Drawing>
    </DrawingImage>
  </Image.Source>
</Image>

производит такое хорошее векторное изображение:

vector image from the source above

Еще одним вариантом может быть использование DrawingBrush, как в этом вопросе SO: Как сохранить и получить несколько фигур в XAML / WPF? .

3 голосов
/ 08 декабря 2010

Вы можете сохранить путь в словаре ресурсов и установить для x: Shared значение false:

<Path x:Key="CrossPath"
      x:Shared="false"
      ...
      />

Это сообщит WPF о создании нового экземпляра при каждом запросе.http://msdn.microsoft.com/en-us/library/aa970778.aspx

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