Dynamically creating Expression Blend controls in WPF C# - c#

I have created a button in Expression Blend 4. I want to dynamically create instances of this button at run time.
The code for the button is below:
<Button Content="Button" HorizontalAlignment="Left" Height="139" Margin="46,107,0,0" VerticalAlignment="Top" Width="412" Grid.ColumnSpan="2">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
</Button>
In addition to the supplying the code can you put comments in explaining what you are doing so that I can learn the general principle.
I know this is a simple question so I have been reading up places such as: Expression blend & WPF, Is there a way to "extract" WPF controls of Expression Blend?, and http://social.msdn.microsoft.com/forums/en-US/wpf/thread/ffa981b8-9bba-43a2-ab5e-8e59bc10fc0d/ unfortunately none of these have helped.

In your WPF application you should have a App.xaml file, in there you can add Styles that are to be used thoughout your UI.
Example:
<Application x:Class="WpfApplication8.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!--The style for all your buttons, setting the background property to your custom brush-->
<Style TargetType="{x:Type Button}"> <!--Indicate that this style should be applied to Button type-->
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
Or if you dont want to apply to all buttons, you can give your Style a Key so you can apply to certain Buttons in your UI
<Application x:Class="WpfApplication8.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!--Add a x:Key value so you can use on certain Buttons not all-->
<Style x:Key="MyCustomStyle" TargetType="{x:Type Button}">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
To use this Style on a Button, just add a binding to the Style property of the Button
<Button Style="{StaticResource MyCustomStyle}" />
this will apply the Style just to this Button
Or if you really want to do it in code behind you can just add the Brush you want to the background
Button b = new Button
{
Background = new LinearGradientBrush(Colors.Black, Colors.White, new Point(0.5, 1), new Point(0.5, 0))
};
its very easy to translate xaml to code because xaml uses the exact same property names, like the code brush I posted above:
new LinearGradientBrush(Colors.Black, Colors.White, new Point(0.5, 1), new Point(0.5, 0))
is ....
Brush(firstColor,secondColor,StartPoint EndPoint)
Xaml just accesses properties in the button, they will all have the same names in C#.

Related

C# WPF Background style for all Windows in ResourceDictionary - Target type with relative path?

I'm organizing my projects with folders. So I have put all window files inside "MyWindows" folder, and in another folder called "Styles" I have a ResourceDictionary. Now I want to write a style for background that would apply to all desired windows, like this:
<Style TargetType="Window" x:Key="Ozadje">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF66A7B6" Offset="0.997"/>
<GradientStop Color="White"/>
<GradientStop Color="#FFAEF1F1"/>
<GradientStop Color="#FFACEAEA"/>
<GradientStop Color="#FF9BF1E6"/>
<GradientStop Color="#FFBFD1CF" Offset="0.06"/>
<GradientStop Color="#FF6CAAB7" Offset="0.924"/>
<GradientStop Color="#FF99BFC4"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="MyWindows/Window1" BasedOn="{StaticResource {x:Type Window}}" />
I can't set this because all Windows are not in a local: namespace that resource dictionary is. And another problem is that styles for windows must be applied manually for each Window via reference.
Is there anything I can do - besides calling Style="{StaticResource Ozadje}" in Window properties?...I'm curious if I can use a relative path.
P.S.: I'm a beginner in WPF.
Define a namespace mapping for the namespace in which Window1 is defined, e.g.:
<Style xmlns:MyWindows="clr-namespace:MyWindows"
TargetType="{x:Type MyWindows:Window1}" BasedOn="{StaticResource Ozadje}" />

Get value for Style from property of the instance to be styled

I would like to create elements during runtime and add a style to them.
Given the following Xaml, I would like to bind the value for the property Center to the actual values of a styled object (see main method). I tried different Binding notations but without success (propably because I am still new to xaml). I also tried to just change the Center on the instance but the instance is frozen and cannot be changed.
<Window x:Name="window" x:Class="CirclePing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="AlertBubble" TargetType="{x:Type Path}">
<Setter Property="StrokeThickness" Value="0"/>
<Setter Property="Data">
<Setter.Value>
<!-- how can I bind Center to the Tag property of a 'styled' instance? -->
<EllipseGeometry x:Name="circle"
Center="200,200"
RadiusX="100"
RadiusY="100">
</EllipseGeometry>
</Setter.Value>
</Setter>
<Setter Property="Fill">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="Black"/>
<GradientStop Color="#2F5CB2"/>
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="OpacityMask">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="#00000000" Offset="0.5"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
</Window>
My Main method:
InitializeComponent();
Random r = new Random();
for (int i = 0; i < 500; i++)
{
var path = new Path();
int positionX = r.Next(1400);
int positionY = r.Next(800);
path.Tag = new Point(positionX, positionY);
path.Style = (Style)this.Resources["AlertBubble"];
}
Now I would like the following to be true: (EllipseGeometry)path.Data).Center.Y == positionY. What binding expression should I use?
You can bind Center using RelativeSource markup extension and finding parent Path instance object like this:
<EllipseGeometry x:Name="circle"
Center="{Binding Tag, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=Path}}"
RadiusX="100"
RadiusY="100"/>

How to allow default value when using binding for custom control

All, I am working on a custom control of ours that has a Border with a Background set to the below
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF7F7F7" Offset="0.164" />
<GradientStop Color="#FFDBDBDB" Offset="0.664" />
<GradientStop Color="#FFB3B3B3" Offset="0.978" />
</LinearGradientBrush>
However, I want to allow the user to override this. I created a dependency property of type Brush, however I cannot figure out how to bind to the Background, while still having this default in the XAML. Is this even possible?
Take a look at the TemplateBinding Markup Extension
<Style TargetType="{x:Type your:YourControl}">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF7F7F7" Offset="0.164" />
<GradientStop Color="#FFDBDBDB" Offset="0.664" />
<GradientStop Color="#FFB3B3B3" Offset="0.978" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
Then in some part of your default ControlTemplate:
<Border Background="{TemplateBinding Background}">
....
</Border>
This will allow the consumer to override the default Background, while maintaining the Style-defined one:
<your:YourControl/> <!-- Will use default Background -->
<your:YourControl Background="Green"/> <!-- will have Green background -->

Styles, datatemplates and triggers

I'm pretty new to WPF and needed a little help. I like to use custom UserControls as Templates instead of defining them in the Style or as ControlTemplates mainly because I can see the outcome as I'm writing the code. This approach was working great when I started but I'm not sure how to check for triggers on my control and change stuff in the UserControl template. Hopefully someone understands what I'm trying to say here. Anyways here's some code. I want to know if an item from ListView[MenuTray] is selected inside the DataTemplate of the ListViewItem control...
MainWindow.xaml
<Window x:Class="Cellestus.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="1000" Height="650" Loaded="Window_Loaded">
<Window.Resources>
<ResourceDictionary Source="/Resources/GlobalResources.xaml" />
</Window.Resources>
<Viewbox x:Name="WindowView" Stretch="Fill">
<Canvas x:Name="WindowCanvas" Width="1000" Height="650" Background="{StaticResource MainWindow_Bg}">
<!-- other stuf... -->
<ListView x:Name="MenuTray" Width="1000" Height="60" Canvas.Bottom="0" Style="{StaticResource MenuTray_Style}" />
</Canvas>
</Viewbox>
</Window>
MainWindow.xaml.cs, Method:Window_Loded
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// MenuTrayItems.List: ObservableCollection<MenuTrayItem>
// MenuTrayItem: Class with a couple of string variables, Title, image, page and etc..
MenuTray.ItemsSource = MenuTrayItems.List;
}
/Resources/GlobalResources.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:class="clr-namespace:Cellestus.Classes"
xmlns:view="clr-namespace:Cellestus.Views">
<!-- Brushes -->
<ImageBrush x:Key="MainWindow_Bg" ImageSource="/Images/Backgrounds/MainWindow.png" Stretch="Fill" />
<LinearGradientBrush x:Key="Gradient_Black" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#2c2c2c" Offset="0" />
<GradientStop Color="#151515" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Gradient_LightGray" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#6B6B6B" Offset="1" />
<GradientStop Color="#D6D7D8" Offset="0" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Gradient_Gray" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#515151" Offset="0" />
<GradientStop Color="#282828" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Gradient_Green" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#77ba53" Offset="0" />
<GradientStop Color="#5a9c37" Offset="1" />
</LinearGradientBrush>
<!-- Templates -->
<ItemsPanelTemplate x:Key="HorizontalListView">
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<DataTemplate x:Key="MenuTrayItem_Template" DataType="{x:Type class:MenuTrayItem}">
<view:MenuTrayItemView />
</DataTemplate>
<!-- Styles -->
<Style x:Key="MenuTray_Style" TargetType="{x:Type ListView}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="{StaticResource Gradient_Black}" />
<Setter Property="ItemsPanel" Value="{StaticResource HorizontalListView}" />
<Setter Property="ItemTemplate" Value="{StaticResource MenuTrayItem_Template}" />
</Style>
</ResourceDictionary>
/Views/MenuTrayItemView.xaml
<UserControl x:Class="Cellestus.Views.MenuTrayItemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary Source="/Resources/GlobalResources.xaml" />
</UserControl.Resources>
<Border x:Name="ItemContainer" Width="150" Height="60" CornerRadius="10" Background="{StaticResource Gradient_Gray}" MouseEnter="ItemContainer_MouseEnter" MouseLeave="ItemContainer_MouseLeave">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Margin="0,3,0,0" Width="60" Height="30" Source="{Binding Image, FallbackValue='/Images/Icons/MenuTray/default.png'}" />
<TextBlock Margin="3,0,0,0" Text="{Binding Title, FallbackValue='title'}" FontSize="10" Foreground="White" />
</StackPanel>
</Border>
</UserControl>
/Views/MenuTrayItemView.xaml.cs
private void ItemContainer_MouseEnter(object sender, RoutedEventArgs e)
{
ItemContainer.Background = FindResource("Gradient_LightGray") as Brush;
}
private void ItemContainer_MouseLeave(object sender, RoutedEventArgs e)
{
ItemContainer.Background = FindResource("Gradient_Gray") as Brush;
}
Here's an image for the visual people:
Well if you made it this far. What I want to know is how to catch the IsSelected value on the ListViewItem control in my DataTemplate / UserControl(MenuTrayView.xaml) and change the background to the static resource "Gradient_Green". I know I can just handle the MouseDown event in my view, but I don't want to do that. I want to know if the item is actually selected.
You need to create a style to your user control, and do something like
<Style TargetType="{x:Type local:MenuTrayItemView}">
<Trigger Property="IsSelected" Value="true">
<Setter Property="background" Value="Static Resource Gradient_Green"/>
</Trigger>
</Style.Triggers>
</Style>
if you ot problems go here WPF Trigger for IsSelected in a DataTemplate for ListBox items

How to define and use resources in xaml so they can be used in C#

Theoretically, I think that I can define Brushes and Colors etc. in an xaml file and assign that to a button.background in c#. But how do I do that? Where do I put my lineargradientbrush definition like this:
<LinearGradientBrush x:Key="BlaBrush">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Green"/>
</LinearGradientBrush>
Just putting it at various places in my window's xaml file results in various error messages :/
I found this question here on stackoverflow: How to use a defined brush resource in XAML, from C# which explains a part of it, but he seems to know where to do the Brush definition.
I also tried adding the shinyblue.xaml wpf template to the app and added <ResourceDictionary Source="ShinyBlue.xaml"/> to the application.resources in app.xaml. This makes all my buttons blue instantly, but still, the "things" defined in shinyblue.xaml like NormalBrush is not accessible from C# - at least I don't know how.
Marc
Your xaml would look something like this:
MainWindow.xaml
<Window x:Class="BrushResource.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<LinearGradientBrush x:Key="BrushOne" StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.5">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="Silver" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="BrushTwo" StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.5">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="Maroon" Offset="0" />
<GradientStop Color="Silver" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Window.Resources>
<StackPanel>
<Button Content="Button" Width="100" Click="myButton_Click"/>
</StackPanel>
To assign the value, you need to grab the gradient brush from the resources like this:
MainWindow.xaml.cs
private void myButton_Click(object sender, RoutedEventArgs e)
{
(sender as Button).Background = this.Resources["BrushOne"] as LinearGradientBrush;
}
Note that the existing answers talk about putting the resources in Window.Resources. If you want the resources to be available application-wide, you might consider putting them in App.xaml or better yet, create stand-alone resource dictionaries that can be included in your views and re-used elsewhere (including other projects)
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DefaultStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="my_style" />
</ResourceDictionary>
</UserControl.Resources>
Put them in the Resources collection of one of your elements in XAML:
<Window ...>
<Window.Resources>
<LinearGradientBrush x:Key="BlaBrush">
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1" Color="Green"/>
</LinearGradientBrush>
<!-- Other resources -->
</Window.Resources>
<!-- Contents of window -->
</Window>
Then get them in code by using FindResource
var blaBrush = this.FindResource("BlaBrush") as LinearGradientBrush;
See Resources Overview for more information.
You can access the application resources as
Application.Current.Resources["BlaBrush"] as LinearGradientBrush
Or, you add the resource to the control's resources and access them like Quartermeister wrote.

Categories

Resources