Можно ли изменить свойства ресурса, созданного с помощью элемента StaticResource в XAML? - PullRequest
0 голосов
/ 03 ноября 2019

С этим фрагментом XAML:

<Window.Resources>
    <Rectangle x:Key="rectangle" x:Shared="False" Width="20" Height="8" Fill="Red" />
</Window.Resources>

<StaticResource x:Name="r1" ResourceKey="rectangle" />
<StaticResource x:Name="r2" ResourceKey="rectangle" />

можно присвоить значение, скажем, свойство Margin, каждому экземпляру независимо с помощью кода:

r1.Margin = 2;
r2.Margin = 5;

Возможно ли этосделать это прямо в XAML? Я попытался:

<StaticResource ResourceKey="rectangle" Margin="3"/>

, но Margin не является свойством StaticResource ...

Перефразирование после срабатывания датчика проблемы XY (соответственно)!

Я хочу нарисовать прямоугольники с точно такими же свойствами, кроме одного, например, поля или цвета, чтобы иметь возможность централизованно изменять общие свойства и по-прежнему иметь возможность предоставлять конкретные свойства в XAML. Могу ли я использовать ресурс как в моей попытке?

Добавление моей точной потребности и кода, как указано в комментариях

Моя точная потребность - показать эффект установки различных свойствк некоторому прямоугольнику, то есть изменяя Rectangle.RenderTransformOrigin и Rectangle.RenderTransform для сравнения эффектов. Это действительно для изучения WPF, а не для производственного приложения. На данный момент я использую стиль (rotated), так как не смог использовать ресурс (это причина моего вопроса выше).

<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Test"
        mc:Ignorable="d"

        Title="Transform Center" Height="400" Width="600">

    <Window.Resources>
        <Style x:Key="title" TargetType="TextBlock">
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Bottom" />
            <Setter Property="Margin" Value="0,0,0,10" />
        </Style>
        <Style x:Key="rotated" TargetType="Rectangle">
            <Setter Property="Width" Value="201" />
            <Setter Property="Height" Value="81" />
            <Setter Property="Fill" Value="CadetBlue"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style x:Key="fixed" TargetType="Rectangle">
            <Setter Property="Width" Value="30" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Fill" Value="Indigo" />
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
    </Window.Resources>

    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <StackPanel Grid.Row="0" Grid.Column="0" Background="Beige" Margin="5">
            <Rectangle Style="{StaticResource fixed}" />
            <Rectangle Style="{StaticResource rotated}" />
        </StackPanel>
        <TextBlock Grid.Row="0" Grid.Column="0" 
                   Style="{StaticResource title}" Text="No rotation" />

        <StackPanel Grid.Row="0" Grid.Column="1" Background="Beige" Margin="5">
            <Rectangle Style="{StaticResource fixed}" />
            <Rectangle Style="{StaticResource rotated}">
                <Rectangle.RenderTransformOrigin>.5,.5</Rectangle.RenderTransformOrigin>
                <Rectangle.RenderTransform>
                    <RotateTransform Angle="20" />
                </Rectangle.RenderTransform>
            </Rectangle>
        </StackPanel>
        <TextBlock Grid.Row="0" Grid.Column="1"
                   Style="{StaticResource title}"
                   Text="RenderTransformOrigin" />

        <StackPanel Grid.Row="1" Grid.Column="0" Background="Beige" Margin="5">
            <Rectangle Style="{StaticResource fixed}" />
            <Rectangle Style="{StaticResource rotated}">
                <Rectangle.RenderTransform>
                    <RotateTransform Angle="20" CenterX="100" CenterY="40" />
                </Rectangle.RenderTransform>
            </Rectangle>
        </StackPanel>
        <TextBlock Grid.Row="1" Grid.Column="0"
                   Style="{StaticResource title}"
                   Text="RotateTransform Center" />

        <!-- The center coordinates relative to the Rectangle are the sum
             of both center coordinates, i.e. .5 + .5 = 1 (bottom-right corner) -->
        <StackPanel Grid.Row="1" Grid.Column="1" Background="Beige" Margin="5">
            <Rectangle Style="{StaticResource fixed}" />
            <Rectangle Style="{StaticResource rotated}">
                <Rectangle.RenderTransformOrigin>.5,.5</Rectangle.RenderTransformOrigin>
                <Rectangle.RenderTransform>
                    <RotateTransform Angle="20" CenterX="100" CenterY="40" />
                </Rectangle.RenderTransform>
            </Rectangle>
        </StackPanel>
        <TextBlock Grid.Row="1" Grid.Column="1" 
                   Style="{StaticResource title}"
                   Text="Both" />

    </Grid>
</Window>

Ответы [ 2 ]

2 голосов
/ 04 ноября 2019

Позволяет ли XAML изменять свойство ресурса при его создании с помощью <StaticResource>

Краткий ответ: №

Расширение разметки StaticResourceпросто ссылается на ресурс на основе ключа. Он не может изменить какие-либо свойства разрешенного ресурса. Вы должны будете установить свойства самого разрешенного ресурса, например, приведя целевое свойство ресурса к Rectangle.

0 голосов
/ 04 ноября 2019

Я хочу нарисовать прямоугольники с точно такими же свойствами, кроме одного, например, поля или цвета

Для меня это звучит как стиль. В WPF, как правило, есть несколько разных способов выполнить одно и то же, и это не исключение.

кажется, что установка модели представления немного завышена

Может быть. Возможно, нет. Трудно сказать, так как в вашем вопросе нет никаких других деталей. Тем не менее, учитывая приведенную выше формулировку проблемы, я бы согласился, что она, безусловно, не необходима , и при отсутствии каких-либо других требований я не вижу ничего, что можно было бы получить с помощью моделей представления.

Тем не менее, вот пример кода, который показывает три различных способа, два из которых основаны на моделях и шаблонах представления:

<Window x:Class="TestSO58683029RectStyle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:l="clr-namespace:TestSO58683029RectStyle"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
  <Window.DataContext>
    <l:MainViewModel>
      <l:MainViewModel.Rectangle1>
        <l:RectangleViewModel Margin="2"/>
      </l:MainViewModel.Rectangle1>
      <l:MainViewModel.Rectangle2>
        <l:RectangleViewModel Margin="5"/>
      </l:MainViewModel.Rectangle2>
    </l:MainViewModel>
  </Window.DataContext>
  <Window.Resources>
    <p:Style TargetType="Rectangle">
      <Setter Property="Width" Value="20"/>
      <Setter Property="Height" Value="8"/>
      <Setter Property="Fill" Value="Red"/>
      <Setter Property="HorizontalAlignment" Value="Left"/>
    </p:Style>
    <DataTemplate DataType="{x:Type l:RectangleViewModel}">
      <Rectangle Width="20" Height="8" Fill="Red" HorizontalAlignment="Left" Margin="{Binding Margin}"/>
    </DataTemplate>
    <x:Array x:Key="rectangleArray1" Type="{x:Type l:RectangleViewModel}">
      <l:RectangleViewModel Margin="2"/>
      <l:RectangleViewModel Margin="5"/>
    </x:Array>
  </Window.Resources>
  <StackPanel>
    <!-- Uses style -->
    <Rectangle/>
    <Rectangle Margin="2"/>
    <Rectangle Margin="5"/>
    <!-- Uses view models, individual properties -->
    <ContentControl Content="{Binding Rectangle1}"/>
    <ContentControl Content="{Binding Rectangle2}"/>
    <!-- Uses view models, collection -->
    <ItemsControl ItemsSource="{StaticResource rectangleArray1}"/>
  </StackPanel>
</Window>

Подходы модели представления основаны на этих классах (они не реализуют INotifyPropertyChangedпотому что в этом простом примере нет необходимости):

class RectangleViewModel
{
    public Thickness Margin { get; set; }
}

class MainViewModel
{
    public RectangleViewModel Rectangle1 { get; set; }
    public RectangleViewModel Rectangle2 { get; set; }
}

Как видно, в случае подхода, основанного на стилях, один элемент <Style/> в словаре ресурсов может использоваться для определениязначения по умолчанию для любых свойств, которые вам нравятся. Затем вы можете явно использовать элемент <Rectangle/> там, где вы хотите, в содержимом вашего окна, явно устанавливая любое другое свойство. Вы можете даже переопределить свойства, которые были установлены в стиле, если это необходимо по какой-либо причине.

Обратите внимание, что в приведенном выше примере шаблон данных явно устанавливает значения своих свойств. Но на самом деле вы можете объединить эти два метода, обращаясь к ресурсу стиля при объявлении шаблона, например, так:

  <DataTemplate DataType="{x:Type l:RectangleViewModel}">
    <Rectangle Margin="{Binding Margin}" Style="{StaticResource ResourceKey={x:Type Rectangle}}"/>
  </DataTemplate>

Как отмечено в комментариях, объявление конкретных элементов пользовательского интерфейса в качестве ресурсов обычно является неправильный способ сделать что-то в WPF. Я не решаюсь сказать, что это всегда неправильно, но я бы сказал, что почти всегда неправильно. Конкретные элементы пользовательского интерфейса должны быть объявлены как фактическое содержимое в XAML со стилями, используемыми для обеспечения форматирования по умолчанию для этих элементов. В противном случае вам следует использовать шаблоны и разрешить WPF создавать элементы пользовательского интерфейса по мере необходимости на основе предоставленного вами шаблона.

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