Make a Button resource and use it in multiple places - c#

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.

Related

How can I change the default style of WPF controls for a single assembly?

I've written a WPF plugin for some off-the-shelf product, and in this plugin I've used a theme/style to change the minimal width of all buttons like so:
<Style TargetType="Button">
<Setter Property="MinWidth" Value="80" />
</Style>
In the newest version of said off-the-shelf product they migrated from winforms to WPF themselves. Now when my plugin is loaded the style that previously just affected my plugged-in forms now affects all buttons in the application. This renders most UI's unusable.
I know I can use dictionary key based resources to make this style specific to my buttons, but this means I have to change each and every button in my plugin by hand, as well as not forget to set the style of each button in the future (and other elements this problem applies to). There are other options to make the style specific to a set of buttons, as seen in Is it possible to set a style in XAML that selectively affects controls? But I'm looking for a way to let my style affect only those of my plugin (so a bit more coarse than talked about in the referenced question). This plugin consists of multiple windows/views (tied together with Caliburn.Micro).
Is there a way to easily scope a style to for instance an assembly or namespace? I'd really like to define my resources just once. Currently it's defined at the Application.Resources level, if there's one more appropriate I'd like to hear that too.
With a ResourceDictionary, we can set default style wich will be applied without define style in Xaml.
DictionayNew.xaml :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<!-- default button -->
<Style TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinWidth" Value="80" />
</Style>
<!-- new button style -->
<Style x:Key="ActionButton" TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="Height" Value="23" />
</Style>
<!-- new button style based on previous style -->
<Style x:Key="BigActionButton"
BasedOn="{StaticResource ActionButton}"
TargetType="{x:Type Button}">
<Setter Property="MinWidth" Value="150" />
<Setter Property="Height" Value="30" />
</Style>
</ResourceDictionary>
In your Xaml, use the dictionary :
<Window x:Class="CheckDoublonImageBing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DictionaryNew.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
</Grid>
</Window>
Then, use Button as usual or with new style
<Button Content="Refresh" />
<Button Content="Delete selected" Style="{DynamicResource ActionButton}" />
With no style defined, button will have default style defined in the dictionary.
EDIT :
You can set merged dictionary by code like this :
ResourceDictionary myResourceDictionary = new ResourceDictionary();
myResourceDictionary.Source = new Uri("DictionayNew.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
You need to specify a Key for your Style and apply the Style to all your Buttons.
<Style TargetType="Button" x:Key="MyButtonStyle">
<Setter Property="MinWidth" Value="80" />
</Style>
<Button Style="{StaticResource MyButtonStyle}"/>
Without a Key the Style is used for all Buttons in the application (as you have already noticed).

How to get the Binding element of a collection inside an item template in WPF?

I have a custom control RadCoverFlow that takes a collection of Image as an itemsSource.
<StackPanel Orientation="Vertical" Background="Black">
<telerik:RadCoverFlow x:Name="coverFlow"
ItemsSource="{Binding ViewImages, Mode=OneWay}"
ItemTemplate="{StaticResource ImageTemplate}"
</telerik:RadCoverFlow>
</StackPanel>
I want to define the widh, the height and a couple of other properties of the Images using a data template. My problem is that in the Data Template, I need to specify a source for each images, but that source is already specified in code.
<DataTemplate x:Key="ImageTemplate">
<Image Source="" Width="100" Height="100" Stretch="Uniform" telerik:RadCoverFlow.EnableLoadNotification="True" />
</DataTemplate>
How can I not re-specify the Source, or bind the source to the Source like {Binding ViewImages[i]}, what would be i in this case?
Thank You
Ideally, your business objects and your UI should be completely separate, so your ItemsSource should not have Image UI objects
But that said, try and use an implicit style to set your properties
<telerik:RadCoverFlow.Resources>
<Style TargetType="{x:Type Image}">
<Setter Property="Height" Value="100" />
<Setter Property="Width" Value="100" />
<Setter Property="Stretch" Value="Uniform" />
<Setter Property="telerik:RadCoverFlow.EnableLoadNotification" Value="True" />
</Style>
</telerik:RadCoverFlow.Resources>

WPF Create instances of controls defined in xaml

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.

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