Entwickler-Ecke

WPF / Silverlight - Canvas-Resource mehrfach - warum greift x:Shared nicht?


Palladin007 - Mo 21.12.15 14:33
Titel: Canvas-Resource mehrfach - warum greift x:Shared nicht?
Hi,

ich habe in meinen Resourcen ein Canvas, das wiederum ein Path enthält.
Das ganze stellt ein Icon darf, das ich an mehreren Stellen verwenden möchte.
Nun stehe ich aber vor dem Problem, das jedes Control nur einen Parent haben kann, daher habe ich dem Canvas x:Shared auf false gesetzt, damit bei jedem Zugriff eine neue Instanz erzeugt wird.
Das hat allerdings keine Auswirkung, das Icon wird nur in einem der Buttons, in denen ich es verwende, korrekt angezeigt, die Anderen haben keinen Inhalt.

Das Canvas:

XML-Daten
1:
2:
3:
<Canvas x:Key="icon_create" x:Shared="False">
    <Path Data="..."/>
</Canvas>


Die Nutzung:

XML-Daten
1:
2:
3:
<Button Command="..."
        Style="{StaticResource DefaultButtonStyle}"
        Content="{StaticResource appbar_create}" />


Und der verwendete Style:

XML-Daten
1:
2:
3:
4:
5:
6:
<Style x:Key="DefaultButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="ContentTemplate" Value="{StaticResource ButtonWithIconContentTemplate}" />
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    <Setter Property="VerticalContentAlignment" Value="Stretch" />
    <!-- many more setter -->
</Style>


Das verwendete Template:

XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
<DataTemplate x:Key="ButtonWithIconContentTemplate">
    <Rectangle>
        <Rectangle.Fill>
            <VisualBrush>
                <VisualBrush.Visual>
                    <ContentPresenter Content="{Binding}"/>
                </VisualBrush.Visual>
            </VisualBrush>
        </Rectangle.Fill>
    </Rectangle>
</DataTemplate>


Das tut erst wie ich will, wenn ich das Canvas in den Resourcen für jede Verwendung manuell kopiere, aber ich kann doch nicht für jeden Button mit diesem Icon einen neuen Eintrag anlegen?
Hat jemand eine Idee, woran das liegt, oder wie ich das umgehen kann?

Beste Grüße


Palladin007 - Di 22.12.15 12:29

Hat niemand eine Idee?


Cjreek - Di 22.12.15 12:48

Funktioniert es denn ohne den Style bzw. das Template?


Palladin007 - Di 22.12.15 14:09

Nein


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
<Button Command="..." HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
    <Button.Content>
        <Rectangle>
            <Rectangle.Fill>
                <VisualBrush>
                    <VisualBrush.Visual>
                        <ContentPresenter Content="{StaticResource appbar_create}"/>
                    </VisualBrush.Visual>
                </VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Button.Content>
</Button>


Was mich auch ein bisschen wundert ist, dass der Code oben zwar funktioniert (bis auf die Tatsache, dass nur ein Button das Icon bekommt), bei folgendem Code wird aber gar kein Icon angezeigt:


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
<Button Command="..." HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
    <Button.Content>
        <Rectangle>
            <Rectangle.Fill>
                <VisualBrush>
                    <VisualBrush.Visual>
                        <StaticResource ResourceKey="appbar_create" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Button.Content>
</Button>


Wenn ich die Visual-Property inline setze, ist natürlich das gleiche
Das ist aber nicht wirklich das Problem, setze ich eben noch einen ContentPresenter dazu, es ist mir einfach aufgefallen.


Cjreek - Di 22.12.15 14:24

Ich meinte eigentlich wenn du dem Content direkt das Canvas aus der Resource zuweist, ohne den VisualBrush.
Weil wenn das nicht klappt wäre das komisch. Wenn doch, dann liegt es irgendwie an dem Brush außendrum.


Palladin007 - Di 22.12.15 14:34

Dann bekomme ich gar kein Icon, egal ob ich den ContentPresenter verwendet, oder die StaticResource direkt in den Content lege.

PS: Wobei das nicht ganz korrekt ist. Scheinbar wird das Icon nicht im Button angezeigt, sondern rutsch hinaus und ist fast nicht mehr im Windows zu sehen, daher ist mir das nicht direkt aufgefallen.
Wenn ich mir aber den Tree zur Laufzeit anschaue, dann sehe ich auch dort wieder: Nur ein Button hat das Icon, wenn auch komisch verschoben, es ist nur in diesem einen Button vorhanden.


Cjreek - Di 22.12.15 16:09

Okay ich habs grad mal selbst probiert und bei mir funktionierts:
(Mini-Testprojekt).


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="window" x:Class="TestProjekt.MainWindow"
        xmlns:local="clr-namespace:TestProjekt"
        Title="Test" Height="561" Width="873">
    <Window.Resources>
        <!--Button-Template-->
        <DataTemplate x:Key="ButtonWithIconContentTemplate">
            <Rectangle>
                <Rectangle.Fill>
                    <VisualBrush>
                        <VisualBrush.Visual>
                            <ContentPresenter Content="{Binding}"/>
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Rectangle.Fill>
            </Rectangle>
        </DataTemplate>

        <!--Button-Style-->
        <Style x:Key="DefaultButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
            <Setter Property="ContentTemplate" Value="{StaticResource ButtonWithIconContentTemplate}" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Stretch" />
        </Style>
        
        <!--Icon resource (Canvas)-->
        <Canvas x:Key="icon_create" x:Shared="False">
            <Path Data="M 0 100 L 100,250" Stroke="Red" StrokeThickness="2"/>
        </Canvas>
    </Window.Resources>
    
    <UniformGrid Rows="5" Columns="5">
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
        <Button Style="{StaticResource DefaultButtonStyle}" Content="{StaticResource icon_create}"/>
    </UniformGrid>
</Window>


Es muss also an irgendwas anderem liegen.


Palladin007 - Di 22.12.15 17:01

Was mir noch an Unterschieden einfällt:
- Icon, Template und Style liegen in einer eigenen Assembly
- Ich nutze MahApps, der Style auf den mein Style basiert, stammt von MahApps

Um heraus zu finden, ob es an einen der beiden Punkte liegt, habe ich folgendes ausprobiert:
- resource direkt in App.xaml gelegt
- BasedOn-Attribut entfernt
Beides macht keinen Unterschied.


Ich denke, wenn hier nicht noch jemand eine Idee hat, lege ich die Resource eben für jeden Button einzeln an.
Ich habe nicht mehr viel Zeit, das Projekt muss fertig werden, da muss eben die schneller "Lösung" genügen


Dir aber auf jeden Fall Danke für deinen Versuch, das Problem zu finden.