WPF Create instances of controls defined in xaml - c#

I have a control defined in xaml with a fairly large number of properties set that is difficult to reproduce in code behind. Can I define the control in xaml and somehow create instances of it in the code behind?

Another option is to create the control as a resource with the x:Shared="False" property if you want to get new instances on each resolution:
<UserControl.Resources>
<Rectangle x:Key="MyControl" x:Shared="False"
...
/>
</UserControl.Resources>
In code:
var myNewCtrl = this.FindResource("MyControl") as Rectangle;
// use control

You can set any number of properties using a Xaml Style, and reapply that style - either directly to a separate instance of the control, or as the base for a different style. The latter would allow you to specify your common properties but still, for example, have different visual settings for each control.
So, instead of trying to reproduce this:
<TextBlock Width="100" Height="40" FontSize="10" ClipToBounds="True" />
... define this in a shared resource file:
<Style TargetType="TextBlock" x:Key="myStyle">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="40" />
<Setter Property="FontSize" Value="10" />
<Setter Property="ClipToBounds" Value="True" />
</Style>
... and then use this in markup:
<TextBlock Style="{StaticResource myStyle}" />
The same principle applies to any control and any set of properties.

Have you considered creating the control as a UserControl?

Yes you can by using XamlReader: http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader.aspx. Use the static method Load passing a stream containing your xaml markup. You obtain an object that is your control instance.

Related

Make a Button resource and use it in multiple places

how can i define a global button and use it in multiple places in WPF.
here is my button witch i want to use it in multiple places.
<Button x:Key="Attach" Width="90" Margin="220,0,0,0" Content="Attach" Height="16" FontSize="11"/>
however i tried to define it in App.xaml(Application.Resources)
and also in MainWindow.xaml (inside Window.Resources)
But i cannot access it in CodeBehind
Button button = Resources["Attach"];
My question is where to define my button and if i defined it correct how to use it in CodeBehind and XAML.
In your App.xaml you will have to add and define a style that you want for your buttons.
<Application.Resources>
<Style x:Key="Attach" TargetType="{x:Type Button}">
<Setter Property="Height" Value="16" />
<Setter Property="Width" Value="90" />
<Setter Property="Content" Value="Attach" />
<Setter Property="Margin" Value="220,0,0,0" />
<Setter Property="FontSize" Value="11" />
</Style>
</Application.Resources>
And to access it in your code-behind you will need to initialize a new style object and populate it with the style you created in your App.xaml. Lastly just add that new style to the style property of your button.
Style style = this.FindResource("Attach") as Style;
Button.Style = style;
In your MainWindow.xaml
<Window.Resources>
<HierarchicalDataTemplate
x:Key="TreeViewMainTemplate"
ItemsSource="{Binding SubTopics}">
<Button
Width="90"
Margin="220,0,0,0"
Content="Attach"
Height="16"
FontSize="11" />
</HierarchicalDataTemplate>
</Window.Resources>
Defining a HiercharchicalDataTemplate with your button layout will allow you to re-use it as an ItemTemplate in your TreeView:
<TreeView
Name="TopicTreeView"
ItemsSource="{Binding Topics}"
ItemTemplate="{StaticResource TreeViewMainTemplate}">
</TreeView>
As you see I'm making intensive use of binding for resources as well as data because I'm building my wpf/sl apps the MVVM way. Doing so makes the need to access controls from code behind obsolete and might be worth looking into for you.

Can binding be used in XAML within a Style?

I wrote a sample to see if binding could be used within a Style in a blank Windows Store app - it compiled but did not work exactly as I'd hoped. I'm relatively new to XAML and binding so may have missed something.
In the sample below there are two rectangles, both bound to the slider control and both should change at the same time as the slider is moved, but it seems that only the first one changes; the first one is bound directly, the second is bound via a style.
Is binding in a Style supposed to be possible in a Win Store app?
(My aim is to have a slider that changes the settings on a large number of elements at once, it seemed like this would be a better approach than copy/pasting bindings to all of them)
<Grid Background="#FF87873D">
<StackPanel>
<StackPanel.Resources>
<Style x:Key="myTestRectangleStyle" TargetType="Rectangle">
<Setter Property="Fill" Value="DarkBlue" />
<Setter Property="Margin" Value="10,10" />
<Setter Property="Height" Value="30" />
<Setter Property="Width" Value="{Binding ElementName=slider1, Path=Value}" />
</Style>
</StackPanel.Resources>
<Rectangle Width="{Binding ElementName=slider1, Path=Value}" Fill="Black" Margin="10,10" Height="30"/>
<Rectangle Style="{StaticResource myTestRectangleStyle}"/>
<Slider Name="slider1" Minimum="20" Maximum="200" Margin="20,0"/>
</StackPanel>
</Grid>
Answering my own question...it seems this isn't possible on a Windows Store App.
I had a clarification from a user on a MSDN forum that
[Bindings] are not supported on Style setters in Windows Store Apps like
they are in WPF, i.e. you cannot bind to the Value property of the
Slider in the Style
So the workaround is just to set the binding directly outside of the Style (a long winded option if you have a lot of elements to bind unfortunately)

How to store FontFamily as a StaticResource?

I'm trying to figure out how to set a FontFamily in my App.xaml in such a way that I can declaratively apply that style wherever I need to.
In the ResourceDictionary I can apply something like:
<System:Double x:Key="SmallTextSize">10</System:Double>
What I want to do then is something like:
<FontFamily x:Key="MainFont">Wingdings</FontFamily>
But, the only thing I can get to work is an implicit style, which requires a target, and multiple declarations of the font I want to use. I need to be able to apply the style I end up with to the FontFamily property of any control.
Here's the closest I can come presently:
<System:String x:Key="MainFont">Wingdings</System:String>
<Style TargetType="UserControl">
<Setter Property="FontFamily" Value="{StaticResource MainFont}"></Setter>
</Style>
This implementation doesn't work on something like because it expects MainFont to be a FontFamily, not a string:
<TextBlock Text="{Binding}" Margin="0,0,0,4" FontWeight="Normal" FontFamily="{StaticResource MainFont}" FontSize="14.667" />
How should I handle this? Thanks!
Not sure I entirely understand this one exactly, since what I do is;
<FontFamily x:Key="MainFont">WingDings</FontFamily>
If you're talking about then applying it to multiple instances without having to declare it to each one then I would just do like;
<Object>
<Object.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource YourDefaultTextBlockStyleToInheritOtherProperties}">
<Setter Property="FontFamily" Value="{StaticResource MainFont}"/>
</Style>
</Object.Resources>
<!-- Your FontFamily automatically gets inherited to all children of the object
whether your object is say a Grid, or StackPanel,
or even an entire UserControl -->
<TextBlock Text="ABCDEFG"/>
<TextBlock Text="12345"/>
<TextBlock Text="!()*&##"/>
</Object>

What is the best way to style a MenuItem for a styled Menu in WPF?

I just started with WPF and would like some advice with the following:
I have a menu that looks like this:
<Menu Name="MenuBar"
Grid.Row="0"
HorizontalAlignment="Right"
Style="{DynamicResource MenuBarStyle}">
<MenuItem Header="Settings" />
<MenuItem Header="Help" />
</Menu>
And in my Window.Resources I have this style defined:
<Style x:Key="MenuBarStyle" TargetType="{x:Type Menu}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="10" />
</Style>
This works as I expected and intended. However, I would also like to alter the Padding property of each MenuItem within my Menu. What is the best way to do this? My initial thought was to create a separate style and apply it to each MenuItem, but how would that work if my MenuItems were dynamically added (they aren't going to be, but just out of curiosity)? Is there a way I can target a child MenuItem from within my "MenuStyle" style?
Thanks,
Steve
You could use an "implicit" style (one without a x:Key-attribute) and target it to the MenuItem-type. This style is then chosen implicitly by default for all MenuItems. Put this style in Menu.Resources if you only want it to be used by this Menu, otherwise in Window.Resources where your Menu-style is.

Setting a style on Control type not working

I'm writing a very basic WPF dialog and want to apply a simple style to all objects that inherit from the Control class. The code I'm using:
<Window.Resources>
<Style TargetType="{x:Type Control}">
<Setter Property="Margin" Value="20"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Text="some text"/>
<TextBox x:Name="x_NameTextBox"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="x_CancelButton" Click="x_CancelButton_Click" Content="Cancel"/>
<Button x:Name="x_OkButton" Click="x_OkButton_Click" Content="OK"/>
</StackPanel>
</StackPanel>
</Window>
The Style defined above doesn't change the layout of the window at all unless I specify a key and set the style on each individual object, which is exactly what I'm trying to avoid. It also works for more specific types (setting the TargetType to Button, for example.)
Any ideas why this isn't working?
Every control when it gets instantiated it gets its Style from the explicitly defined resource or look for the immediate parent where it can get a default style. In your case the Button control will get its default Style from the platform because your App haven't defined one. Now that platform Button Style has no way to know about your custom defined Control base style. Because styles will look for a base style only when you explicitly define BasedOn
So you got only two ways
1. Define Style for every control - which you don't want I think.
2. Define Styles for the controls you are interested and set the BasedOn
<Style TargetType="{x:Type Control}">
<Setter Property="Margin" Value="20"/>
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Control}}">
</Style>

Categories