Clone ResourceDictionary Object - wpf

Say that I have the object:
<Grid x:Key"FooGrid>
<!--Content Here-->
</Grid>
And I normally reference it by something like:
<ContentPresenter Content="{StaticResource ResourceKey=FooGrid}"/>
And while this works, if I call it a second time, it removes the first use and moves it to the requested second use.
Clearly there's an issue of my method of calling the resource. What would be a better way of going about this, if I want a unique instance of the object, similar to what Style can create?
I'd use style, but as I understand it Style doesn't support defined content.

You can use the x:Shared attribute to do this, e.g.:
<Grid x:Key"FooGrid" x:Shared="False">
<!--Content Here-->
</Grid>

Excuse-me if my english is bad..
This happens,because the element is logical child of other element.
But the ContentPresenter is not a ContentControl, then he do this approach.
if you try the same thing with a ContentControl, you get a Runtime Error.
See:
http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter.content
Att,
Allan

I used "a little sheep" answer to add
x:Shared="False"
but it ruined structure of VisualBrush, so I added to code
VisualBrush vb = Application.Current.Resources["MyBrushName"] as VisualBrush;
VisualBrush newVB = vb.Clone();
and it justified my endeavours.
Using only .Clone() doesn't work.

Related

Skinning Control Backgrounds - Better Performance?

sorry if this question is overly simple, but I'm having a hard time figuring out how to create backgrounds to controls - in the hopes that it will improve app performance.
I have 9 different controls. All of them have a background. The backgrounds are made up of either images, other controls or both. All of those backgrounds have another background.
Think of this like Power Point with slides, slide layouts and slide masters - inherited in that order. I have 9 slides / controls.
The first 3 controls have the same "control layout" (let's call it
ControlLayout1). ControlLayout1 gets some of it's elements from ControlMaster1.
The second 3 controls also have the same control layout, but it is
different from the first. Let's call it ControlLayout2. It also
inherits from ControlMaster1.
The final set of 3 controls are different again. We can call them
ControlLayout3. But this time, they inherit from a different master - ControlMaster2.
Right now in each control I'm writing out all the XAML each time separately. I'm thinking there must be a way to not write these in each of these each item. Ideally, what I would like to create is one set of XAML that can be reused.
Here's some pseudo-XAML:
<UserControl x:Name="Control1">
<MyBackground (ControlLayout1)/>
</UserControl>
<UserControl x:Name="Control2">
<MyBackground (ControlLayout2)/>
</UserControl>
<UserControl x:Name="Control3">
<MyBackground (ControlLayout3)/>
</UserControl>
And then somewhere for ControlLayouts (I don't know, like Application.Resources or elsewhere)
<Canvas x:Name="ControlLayout1">
<MyMasterBackground (ControlMaster1)/>
</Canvas>
<Canvas x:Name="ControlLayout2">
<MyMasterBackground (ControlMaster1)/>
<TextBox Text="The Control 2">
</Canvas>
<Canvas x:Name="ControlLayout3">
<MyMasterBackground (ControlMaster2)/>
<TextBox Text="The Control 3">
</Canvas>
And then for the ControlMasters
<Canvas x:Name="ControlMaster1">
<Canvas.Background>
<ImageBrush ImageSource="/Images/image1.jpg" />
</Canvas.Background>
</Canvas>
<Canvas x:Name="ControlMaster2">
<Canvas.Background>
<ImageBrush ImageSource="/Images/image2.jpg" />
</Canvas.Background>
<TextBox Text="Control Master 1">
</Canvas>
Once defined, the ControlLayouts and ControlMasters never need to change - they are static.
Beyond just having a smaller XAP if I can put these all in one location and reuse the XAML, I'm hoping performance will be improved in my app as the ControlLayouts automatically get BitmapCached or something like that.
So first, is there a good strategy to implement the above (the ControlLayouts and Masters do not have any code-behind)? Secondly will performance be improved in loading of Control1, Control2, etc.? Finally, if they were pure usercontrols (i.e. they had some code behind), would that be better for performance?
Thanks in advance!
What you ask for is a combination of a few things:
About the Background thing: just create a dependency property (let's call it MyBackgroundDP) of type Brush in the code behind of a UserControl, and bind it to your XAML like:
<UserControl ...>
<Grid Background={"Binding MyBackgroundDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}">
<!-- More XAML declarations -->
</Grid>
</UserControl>
To create the dependency property, you can use the built in snippet in visual studio: propdp
Simply write "propdp" and that TAB twice. Fill up the fields and it's all good.
Alright so that was easy enough, right? ;)
Now the tougher part: making so-called master pages.
Actually it's not that much different from the background thing.
Declare another dependency property, only this time of type object, or FrameworkElement (better).
Then in your XAML, you declare a kind of placeholder: ContentControl. Let's call it MyContentDP for this example:
<UserControl ...>
<Grid Background={"Binding MyBackgroundDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}">
<ContentControl ContentTemplate="{Binding MyContentDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}" />
</Grid>
</UserControl>
You can then fine tune whatever else you want to provide in this "master view", add a border around the Grid, put some flowers, you name it.
Once you're done, this is how you use it, assuming it was called MyUserControl
<Window ...
xmlns:local="...reference_to_your_usercontrol_dll/exe">
<Grid>
<local:MyUserControl MyBackgroundDP="Red">
<local:MyUserControl.MyContentDP>
<!-- More XAML declarations here -->
</local:MyUserControl.MyContentDP>
</local:MyUserControl>
</Grid>
</Window>
Now the performance point:
If you put all the XAML for this as a Custom control (which is DIFFERENT from a UserControl), you can then put all the XAML in your App.xaml
Why? because parsing XAML can be an intensive operation, and if you make WP7/SL parse it at runtime whenever you need it, you lose performance.
Instead, your App.xaml gets parsed at startup, then it's in memory. That's what's done in the loading of your application. You would get a performance boost, although it would be minimal for controls made of few XAML, it is still a good practice.
Hope this helps,
Bab.

For WPF, Is it overkill to use a setter to set the itemtemplate property?

When I searched the internet to find out how to set the itemtemplate for a listbox, I found an example where they used a Style Setter in the window.resources to do this. So, I have a couple of options, I can either create a datatemplate in my window.resources, or, create a Style Setter. Would it be overkill to set the style instead of the datatemplate? Which method should I use?
Thank You.
You can't say one or the other is better, it depends. Implicit DataTemplates are a nice way to globally (even if just for part of the visual tree) how a Type should look. While using ItemTemplate allows you to indicate how it should look in a given ItemsControl (i.e. ListBox, ComboBox, etc.).
You can even use a combination of both of them, which allows you have a "default" look, but customize it per control or control type.
Even with ItemTemplate, you can set it globally for say all ListBoxes, or for just one ListBox instance. So again, sometimes one method is better, sometimes not. It depends on what you are trying to do.
Styles in general are used to apply the same values to different instances of the same type. If this is not the case there is no need to create a style at all.
I prefer to make a <DataTemplate> for the type of item and then let WPF figure it out.
<DataTemplate DataType="{x:Type local:Task}">
<StackPanel>
<TextBlock Text="{Binding Path=TaskName}" />
<TextBlock Text="{Binding Path=Description}"/>
<TextBlock Text="{Binding Path=Priority}"/>
</StackPanel>
</DataTemplate>
<List ItemSource="{Binding MyListOfTaskItems"/>

Should I be using UserControls for my Views instead of DataTemplates?

I was reading this post and the author makes the suggestion that using DataTemplates to define a ViewModel is a lunatic's way to do it (#7). I do that all the time, is it really that bad?
<DataTemplate DataType="{x:Type local:MyViewModel}">
<Grid>
...
</Grid>
</DataTemplate>
Most of my Views are simply a ResourceDictionary that defines a DataTemplate or two. To me, it makes much better sense to do this than creating a UserControl for every ViewModel. Why would I want the extra layer in WPF's visual tree when it's not needed? And why would I want to take care of mapping ViewModels to Views when a DataTemplate does that for me? Is this syntax really a "lunatics approach"?
Nothing bad about it, except for incredibly large xaml files and the lack of edit support that DataTemplates have on the design surface.
If those issues are hurting you, you can always...
<DataTemplate DataType="{x:Type local:MyViewModel}">
<local:MyViewModelUserControl />
</DataTemplate>
The good thing with DataTemplate is that they are strongly typed to Viewmodel classes. All you need to do is create a ContentPresenter in View and Bind DataContext to VM. If your DataTemplate is defined in a ResourceDictionary and has a DataType attribute instead of Key, WPF will internally figure out the right DataTemplate for the VM class and display it.
But as you mentioned, we cannot create the DataTemplate in a seperate file. So the file where the DataTemplates exist in ResourceDictionary (e.g. App.xaml), the file gets really messy and it becomes difficult to manage the code soon.
So my take is, if the VM is simple create a DataTemplate. Or else it is always better to create a seperate UserControl and bind its content to the VM.
I run into the issue with performance. There is difference between next two case:
1.
<DataTemplate DataType="{x:Type local:MyViewModel}">
<!-- xaml is moved to separate user control -->
<local:MyViewModelUserControl />
</DataTemplate>
2.
<DataTemplate DataType="{x:Type local:MyViewModel}">
<!-- xaml is typed here directly -->
<Border>
...
</Border>
</DataTemplate>
In 1st case it takes longer to render results than in the 2nd. And this difference is in about 2 times.
I posted it as a separate question

Silverlight 4: ContentTemplate Background Change

I have a Header style for my datagrid custom header. I am using theme for my application. The problem here is the header background of the datagrid is not changing however when I remove the styles, the header background has no problem, it change.
Here's the themes
Here's my sample application, right click the grid and context menu will appear for the list of themes, select the different themes. I have two columns namely, with header style and without header style. See the difference. Thank you for your help.
<Style x:Key="DataGridHeaderStyle" TargetType="primitive:DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding}" Grid.Column="0" HorizontalAlignment="Left" />
<filter:DataGridColumnFilter Grid.Column="1" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Thank you
I did a quick test, and it does not seem to work with either the tag approach or the ImplicitStyleManager attribute approach. This is probably because the style setter is outside the scope and therefore gets applied without a theme.
Suggestion 1: Look at the way that the Jet Pack theme handles it with resource dictionaries in App.xaml, and try to do something similar. (You will need the theme.xaml file for this. EDIT: This link might help.) If you want to change the theme dynamically, then consider this (old) post about swapping themes in resource dictionaries (I haven't tried it, but it should work).
Suggestion 2: You need to think about style inheritance. Since "BasedOn" needs an x:Key tag, you could instead copy the theme's implicit DataGridColumnHeader style and only modify the parts you are interested in. (I don't know if there's a more elegant way.)
If this is not what you meant, then please provide more sample code.
EDIT [2010-12-09]:
I looked at the code, and I believe the root of the problem is the absence of style inheritance. Your "DataGridHeaderStyle" is saying "Do not use the normal DataGridColumnHeader style, but instead use this TextBlock inside this Grid." So Silverlight does just that: it gives you a styled TextBlock in an unstyled default DataGridColumnHeader.
Proof: Update your "Home.xaml" and add a TextBox in the second column of your "DataGridHeaderStyle" style, next to the current TextBlock. Notice how the theme for the TextBox in the header is changing every time you change the theme (look at the TextBox backgroud), but the background of the column header is stuck on the default colour. Like I said, your custom style is telling Silverlight to ignore the implicit style.
FIX: I do not know how to inherit from implicit styles without an "x:Key" attribute. I googled quite a bit but could not find anything helpful. You will either have to a) create a custom column definition style for all your datagrid headers, or you will have to b) bother the Silverlight team for a new feature in the next version of Silverlight. Or c) pick one theme to stick with and edit a copy of the theme's implicit column header style as your new "DataGridHeaderStyle" style.
My holiday is about to start, so I hope this helped. At least now you know where the problem lies.

WPF change ItemsPanel and ItemTemplate in code behind

I have the following list in XAML:
<ListView Name="ListViewBack"
Margin="3"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsPanel="{StaticResource IconListPanelTemplate}"
ItemTemplate="{StaticResource IconListDataTemplate}">
</ListView>
Now I would like to be able to change the ItemsPanel and ItemTemplate from the List to the Grid version. I've tried this using the following code:
ListViewBack.ItemsPanel = Resources["IconGridPanelTemplate"] as ItemsPanelTemplate;
ListViewBack.ItemTemplate = Resources["IconGridDataTemplate"] as DataTemplate;
But nothing happens when excecuted.
Any idea's?
Thanks!
Your obvious problem is that you are using Resources[] instead of FindResource(). In general, Resources[] will only work if your resource is in the this.Resources dictionary, and not elsewhere.
This is how I would rewrite your two lines of code:
ListViewBack.ItemsPanel = (ItemsPanelTemplate)ListViewBack.FindResource("IconGridPanelTemplate");
ListViewBack.ItemTemplate = (DataTemplate)ListViewBack.FindResource("IconGridDataTemplate");
Acutally I would be more likely to use triggers or use DynamicResource and swap resource dictionaries for this purpose, but that's another story.
Note that I called ListViewBack.FindResource() instead of just FindResource(). This is in case where IconGridPanelTemplate is redefined in a resource dictionary below the UserControl level. If this will never be possible, you can simply call FindResource().
You need to style your ListView.View, not the ListView itself.
Check the documentation for the ViewBase Class for an example.

Resources