Вопрос по wpf, xaml, resources, c# – спасибо за объяснение того, что на самом деле делает shared = false, это решило мою проблему

8

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

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

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

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

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

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

<Path Style={StaticResource VectorImage1}/>

Кажется, это многоразовый способ, но меня волнуют две проблемы:

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

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

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

Ваш Ответ

3   ответа
5

После некоторых исследований есть еще один вариант: использование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>

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

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

@LonelyPixel: я исправил ссылку и добавил пример. Vlad
Пример ссылки не работает и не может быть восстановлен. (Содержимое MSDN для этого участника не имеет примеров.) Есть ли у кого-нибудь контент, которым можно поделиться на этом сайте? ygoe
@BTownTKD: вы правы, я постараюсь построить несколько примеров Vlad
Я предпочитаю такой подход, но я думаю, что ответ выиграл бы от некоторых примеров встроенного кода. Использование DrawingImage позволяет объединить несколько векторной графики (и несколько цветов) в один связный значок, используя элемент <DrawingGroup /> в качестве свойства содержимого DrawingImage. Это также позволяет вам - в вашем коде пользовательского интерфейса - всегда использовать элемент <Image /> для ваших значков, независимо от того, ссылаетесь ли вы на векторное изображение или растровое изображение; свойство «Source» будет ссылаться на векторный ресурс DrawingImage или на ресурс изображения BitmapSource. BTownTKD
14

Вы можете добавить атрибут 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>
Большое спасибо, ваше предложение работает очень хорошо :-) Vlad
@ Влад @ Я обновил свой пример. Если вы попробовали пример со StackPanel, я забыл переместить атрибут x: Shared в StackPanel. Fredrik Hedblad
Понимаю, мой плохой, я должен был попытаться понять, что именно говорится в сообщении. С x: Shared только на верхнем уровне это работает. Vlad
@Vlad: Да, я получил то же исключение, когда пытался запустить его .. Это хорошо проявилось в дизайнере, поэтому я даже не стал пытаться запустить его :) Fredrik Hedblad
Я попытался использовать ваше предложение, но во время выполнения я получил исключение: «Общий атрибут в пространстве имен« http: //schemas.microsoft.com/winfx/2006/xaml »может использоваться только в скомпилированных словарях ресурсов». я переехалMyVectorImage в отдельный словарь ресурсов XAML, но я получаю то же сообщение об ошибке при включении этого словаря в MergedDictionaries окна. Vlad
3

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

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

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

спасибо за объяснение того, что на самом деле делает shared = false, это решило мою проблему EdwardM
большое спасибо; Ваше предложение в основном совпадает с принятым ответом. Vlad
это будет работать для произвольных фрагментов WPF? Например.,Canvas с подэлементами? Vlad

Похожие вопросы