Создайте элемент управления в ресурсах и повторно используйте его в XAML WPF

Я просто пытаюсь создать простой Symbol/Geometry/Control и изменить и повторно использовать его в нескольких местах в одном окне.

Пример: черный квадрат с окружностью посередине.

Затем круг должен меняться между красным и зеленым (аналогично однокрасочному стоп-сигналу). Работа с изображениями будет работать. Я пытаюсь разрешить его как ресурс Window, но я не отключаюсь.

Идея: я пишу ее в ресурс, здесь я пытаюсь использовать Canvas:

<Window.Resources>
    <Canvas x:Key="Ampel">
        <Rectangle Fill="Black" HorizontalAlignment="Left" Height="52" Stroke="Black"       VerticalAlignment="Top" Width="50"/>
        <Ellipse x:Name="RedGreen" Fill="Red" HorizontalAlignment="Left" Height="27" Margin="11,12,0,0" Stroke="Black" VerticalAlignment="Top" Width="28" RenderTransformOrigin="0.214,0.256"/>
    </Canvas>
</Window.Resources>

Затем я хотел бы поместить его внутри Grid или панели, но как мне это сделать?

<Canvas x:Name="RedGreen1" Height="50" Width="50" DataContext="{DynamicResource Ampel}" /> 

Это не возвращает ошибку компилятора, но ничего не показывает в окне. Он также не работает с WrapPanel или чем-либо еще.

И если это сработает, как я могу ссылаться на него в коде, чтобы изменить цвет круга. Что-то вроде RedGreen1.RedGreen.Fill=Brushes.Green?

Я читал статьи о стоп-сигналах. Действительно ли необходимо создать UserControl или есть способ решить его с помощью window.resources?

Общая идея приложения - иметь список параметров. Каждый с правильным вводом отмечен зеленым, и вычисление может быть запущено, только если все параметры отмечены зеленым.

И даже если я его запускаю с красными/зелеными изображениями, я пытаюсь лучше понять WPF/XAML и узнать что-то.

Спасибо.

Ответы

Ответ 1

Когда вы определяете произвольный элемент управления в Resources, вы можете использовать его в будущем в элементе управления, у которого есть свойство Content и получено из класса Control. Это следующие: ContentControl, Label, ContentPresenter и т.д.

Также вы должны установить x:Shared="False" для ресурса, если вы хотите использовать этот ресурс во многих элементах управления, потому что x:Shared="True" по умолчанию один ресурс является общим для всех - в этом случае система ругается по дублированному Контенту. Когда x:Shared="False", когда создается ресурс для каждого элемента всякий раз, когда он запрашивает его. Цитата из MSDN:

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

Пример:

<Window.Resources>
    <Canvas x:Key="Ampel" x:Shared="False">
        <Rectangle Fill="Black" HorizontalAlignment="Left" Height="52" Stroke="Black" VerticalAlignment="Top" Width="50"/>
        <Ellipse x:Name="RedGreen" Fill="Red" HorizontalAlignment="Left" Height="27" Margin="11,12,0,0" Stroke="Black" VerticalAlignment="Top" Width="28" />
    </Canvas>
</Window.Resources>

<Grid>
    <ContentControl Name="MyContentControl" Content="{StaticResource Ampel}" HorizontalAlignment="Left" />        
    <Label Name="MyLabel" Content="{StaticResource Ampel}" HorizontalAlignment="Center" />
    <ContentPresenter Name="MyContentPresenter" Content="{StaticResource Ampel}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>

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

private void ChangeBackground_Click(object sender, RoutedEventArgs e)
{
    var canvas = MyContentControl.Content as Canvas;

    if (canvas != null)
    {
        foreach (var item in canvas.Children)
        {
            if (item is Ellipse)
            {
                ((Ellipse)item).Fill = Brushes.Green;
            }
        }
    }
}

Ответ 2

canvas не имеет свойства template, поэтому мы используем здесь contencontrol.

<Window.Resources>
    <ControlTemplate x:Key="Ampel" TargetType="ContentControl">
        <Canvas>
            <Rectangle Fill="Black" HorizontalAlignment="Left" Height="52" Stroke="Black" VerticalAlignment="Top" Width="50"/>
            <Ellipse x:Name="RedGreen" Fill="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" Height="27" Margin="11,12,0,0" Stroke="Black" VerticalAlignment="Top" Width="28" RenderTransformOrigin="0.214,0.256"/>
        </Canvas>
    </ControlTemplate>
</Window.Resources >

<ContentControl  Template="{StaticResource Ampel}" Tag="Red" ></ContentControl>
<ContentControl  Template="{StaticResource Ampel}" Tag="Green" ></ContentControl>
<ContentControl  Template="{StaticResource Ampel}" Tag="Blue" ></ContentControl>

Выход

enter image description here

Ответ 3

Вы можете использовать код С# по наследству:

public class customBottum : Buttom
{
        int var1;
        bool var2;

        public customBottum()
        {
            InitializeComponent();
        }

        other function ...
}