Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a control in Resources and reuse it in XAML WPF

I just try to create a simple Symbol/Geometry/Control and change and reuse it in several places in the same window.

Example: a black square with a circle in the middle.

The circle should then change between red and green (similar to a one-light stoplight). Doing it with images would work. I try to solve it as a Window resource, but I do not unterstand.

The idea: I write it into a resource, here I try into a 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>

Then I would like to place it inside a Grid or a Panel, but how do I reference it?

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

This does not return a compiler-error, but shows nothing in the window. It also doesn't work with WrapPanel or anything else.

And if it would work, how could I refer to it in code-behing for changing the color of the circle. Something like RedGreen1.RedGreen.Fill=Brushes.Green?

I read the articles about stoplights. Is it really necessary to create an UserControl or is there a way to solve it with window.resources?

General idea of the application is to have a list of parameters. Each one with a correct input is marked green and computation can only be started, if all parameters are marked green.

And even if I get it running with red/green-images, I try to understand WPF/XAML better and learn something.

Thank you.

like image 456
user3367867 Avatar asked Apr 09 '14 10:04

user3367867


People also ask

How do I add Resources to XAML dictionary?

Tip You can create a resource dictionary file in Microsoft Visual Studio by using the Add > New Item… > Resource Dictionary option from the Project menu. Here, you define a resource dictionary in a separate XAML file called Dictionary1. xaml.


2 Answers

When you define a arbitrary Control in Resources, you can use it in the future in Control which have property Content and derived from Control class. These are the followings: ContentControl, Label, ContentPresenter, etc.

Also you must set x:Shared="False" for resource if you want to use this resource in many Controls, because x:Shared="True" by default then one Resource is common to all - in this case, the system swears on the duplicate Content. When x:Shared="False" when is created Resource for each element whenever it its request. Quote from MSDN:

When set to false, modifies WPF resource-retrieval behavior so that requests for the attributed resource create a new instance for each request instead of sharing the same instance for all requests.

Example:

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

To change the Fill of Ellipse in code-behind, you can like this:

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;             }         }     } } 
like image 107
Anatoliy Nikolaev Avatar answered Sep 18 '22 14:09

Anatoliy Nikolaev


canvas is not having template property thats why we are using contencontrol here.

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

Output

enter image description here

like image 30
Heena Avatar answered Sep 19 '22 14:09

Heena