Question

I have an ItemsControl which renders some Point into apropriately positioned ellipses similar to small dots in a 2D map.

Since my screen contains drawings where the same ItemsControl must be displayed many times, I tried to make it into StaticResource, but two things were wrong:

  1. When I try to instantiate the same resource multiple times, the second times give an error. I have read in other answer that this is because StaticResources are, well, static, and you cannot have two instances of a static Control in the Visual Tree at the same time;

  2. Whe I instantiate only one, the Element Binding to PainelMarc.ActualHeight (for example) does not work;

So my goal is to DRY up my XAML by converting this ItemsControl, or parts of it, into reusable resources.

<ItemsControl  x:Name="PainelMarc"
    ItemsSource="{Binding ExameAtivo.ListaMarcadores, Mode=TwoWay}" Grid.Row="1" Grid.RowSpan="3">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>                      
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="{x:Type FrameworkElement}">
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource MarcadoresConverter}">
                        <Binding />
                        <Binding ElementName="PainelMarc" Path="ActualHeight"/>
                        <Binding ElementName="PainelMarc" Path="ActualWidth"/>
                        <Binding Source="{StaticResource LimitesFrontal}" Path="Geometry.Bounds"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>                   
        </Style>                
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="Double">
            <Canvas>
                <Ellipse x:Name="elipsemouseover"
                    Width="10"
                    Height="{Binding Width, RelativeSource={RelativeSource Self}}"
                    Fill="White" Stroke="Black" StrokeThickness="1" RenderTransformOrigin="0.5,0.5">
                    <Ellipse.RenderTransform>
                        <TranslateTransform X="-5" Y="-5"/>
                    </Ellipse.RenderTransform>
                </Ellipse>
            </Canvas>
        </DataTemplate>             
    </ItemsControl.ItemTemplate>
</ItemsControl> 
Was it helpful?

Solution

Set x:Shared="False" on your resource so that everytime resource lookup is done via StaticResource, it returns new instance of resource.

Default value is true for all resources. Hence, you are getting the error regarding addition of same control in different Visual Trees.

From MSDN link of x:Shared:

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.


And for second question that ElementName binding not working. That should work fine, I see no issue in that code. Your converter should fire successfully.

Just in case it doesn't, you can try with RelativeSource in place of ElementName to get ItemsControl:

<Binding RelativeSource="{RelativeSource Mode=FindAncestor,
                            AncestorType=ItemsControl}" Path="ActualHeight"/>
<Binding RelativeSource="{RelativeSource Mode=FindAncestor,
                            AncestorType=ItemsControl}" Path="ActualWidth"/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top