I have a ResourceDictionary to define my custom Window style. I am using WindowChrome to style my MainWindow by adding a custom title bar to it that has a button control. Question: Using C# in the code behind file MainWindow.cs, how can I access the button control btnTest residing inside the following MyWindowChrome.xaml file:
MyWindowChrome.xaml:
<ResourceDictionary x:Class="MyWPFProject.WindowStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWPFProject">
<Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome ResizeBorderThickness="5" UseAeroCaptionButtons="False" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<DockPanel>
<Button x:Name="btnTest" WindowChrome.IsHitTestVisibleInChrome="True"/>
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
App.xaml
<Application x:Class="MyWPFProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:main="clr-namespace:MyWPFProject"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyWPFProject;component/WindowStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
You didn't show how/when you apply the Style. Assuming that you set the FrameworkElement.Style directly in the XAML file, you should be able to get the template elements when FrameworkElement.Loaded was raised:
MainWindow.xaml.cs
partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
var button = this.Template.FindName("btnTest", this) as Button;
}
}
Related
I'm trying to create a custom version of UserControl to implement some standard animations for views when loading.
But when I add a ContentPresenter I'm not able to add content to my control. Why though?
Here is the Template I use for my custom control.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:EzNintendo.Desktop.Controls">
<Style TargetType="{x:Type local:AnimatedView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:AnimatedView}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
and the default code for a custom control
public class AnimatedView : Control
{
static AnimatedView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedView),
new FrameworkPropertyMetadata(typeof(AnimatedView)));
}
}
and
and that is how I try to use it.
<controls:AnimatedView x:Class="MyView"
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"
xmlns:controls="clr-namespace:MControls;assembly=MControls">
<Grid>
<TextBlock Text="Hello World!" />
</Grid>
</controls:AnimatedView>
When I remove the Grid it works just fine.
I have a template with a Style that uses an EventSetter to set a common event handler to some Hyperlinks. But I want to handle this event not in the resource dictionary's .cs file but in the custom control's .cs file. How can I do this? I am in the process of moving resources into theme .xaml files. I thought about separating the functionality part of the Hyperlink style, but where should I put the event setter? I thought I can use commands, but is there a more concise tehnique that does not require changing each Hyperlink element and works for elements that do not support commands?
I use .NET Framework 4.7.2. I have made a few searches over the web and a simple test example:
App.xaml
<Application x:Class="wpf_test_2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_test_2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Dictionary.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_test_2">
<ControlTemplate x:Key="MyControlTemplate">
<ControlTemplate.Resources>
<Style TargetType="Button">
<!-- obviously, this does not compile: -->
<EventSetter Event="Click" Handler="MyHandler"/>
</Style>
</ControlTemplate.Resources>
<UniformGrid Rows="5" Columns="5">
<Button>A</Button>
<Button>B</Button>
<Button>C</Button>
<Button>D</Button>
<Button>E</Button>
<Button>F</Button>
<Button>G</Button>
<Button>H</Button>
<Button>I</Button>
</UniformGrid>
</ControlTemplate>
</ResourceDictionary>
MainWindow.xaml
<Window x:Class="wpf_test_2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:wpf_test_2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:MyControl/>
</Grid>
</Window>
MyControl.xaml
<Control x:Class="wpf_test_2.MyControl"
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"
xmlns:local="clr-namespace:wpf_test_2"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Template="{DynamicResource MyControlTemplate}">
</Control>
MyControl.xaml.cs
/// <summary>
/// Interaction logic for MyControl.xaml
/// </summary>
public partial class MyControl : Control
{
public MyControl()
{
InitializeComponent();
}
private void MyHandler(object sender, RoutedEventArgs e)
{
var b = sender as Button;
MessageBox.Show($"Button {b.Content.ToString()} was clicked!");
}
}
Screenshot
Expected: the project compiles, and when I click one of the buttons, a MessageBox appears with the content of the button as string.
Actual: the project does not compile.
Thank you.
Inspired by Clemens' comment, I created a RoutedUICommand, a corresponding command binding, and setters which set Command and CommandParameter:
AboutWindow.xaml
<Window
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"
xmlns:local="clr-namespace:cs_timed_silver"
x:Class="cs_timed_silver.AboutWindow"
mc:Ignorable="d"
Width="448" Height="200" ResizeMode="NoResize"
WindowStartupLocation="CenterOwner"
Loaded="Window_Loaded"
Closed="Window_Closed"
Style="{DynamicResource AboutWindowStyle}">
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:AboutWindow.NavigateCommand}"
CanExecute="CommandBinding_CanExecute"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
</Window>
AboutWindow.xaml.cs
public partial class AboutWindow : Window
{
public static RoutedUICommand NavigateCommand { get; set; } =
new RoutedUICommand("", "NavigateCommand", typeof(AboutWindow));
[...]
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
System.Diagnostics.Process.Start(
new System.Diagnostics.ProcessStartInfo((e.Parameter as Uri).AbsoluteUri));
}
Light.xaml
<Style x:Key="AboutWindowStyle" TargetType="local:AboutWindow">
[...]
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<ControlTemplate.Resources>
[...]
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="Command" Value="{Binding NavigateCommand}"/>
<Setter Property="CommandParameter"
Value="{Binding RelativeSource={RelativeSource Mode=Self}, Path=NavigateUri}"/>
</Style>
</ControlTemplate.Resources>
[...]
I've added some styling to an application's buttons and now the click event only fires if you click on the text of the button (because it fires the TextBox click event which bubbles up).
Here's the Snoop trace of two clicks on the button. The first click was inside the button but outside the text area. The second click fired the event to show the Click detected MessageBox:
app.xaml:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style x:Key="RoundedButton" TargetType="{x:Type Button}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Height" Value="26"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" BorderBrush="LightGray" BorderThickness="2" Padding="2">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="88.298" Width="223.936">
<Grid>
<Button Name="ClickMe" Width="70" Margin="0,0,30,0" Style="{DynamicResource RoundedButton}" Click="ClickMe_Click">Click Me</Button>
</Grid>
MainWindow.cs
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ClickMe_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Click detected");
}
}
}
Put a non transparent (or near to transparent) background for the Border in the Template of the button.
I created a CParametres object in my app.xaml.cs like this :
public partial class App : Application
{
public CParametres myParamObject;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
myParamObject = new CParametres(System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) +#"\BingMapsParam.ini");
if (myParamObject.LoadParams() == false)
{
return;
}
Resources.Add("myParamObject", myParamObject);
}
}
Now, in my app.xaml, i add a Dictionnary :
<Application x:Class="myGeoloc.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
And, here is my Dictionnary :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:t="clr-namespace:myGeoloc"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF">
<t:CParametres x:Key="myParamObject"/>
<Style TargetType="m:Pushpin" x:Key="PushpinStyle_Fournisseur">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="m:Pushpin" >
<!-- <Image Stretch="Fill" Source="C:\Users\FabioWalter\Documents\Visual Studio 2013\Projects\myGeoloc\myGeoloc\bin\Debug\Pushpins\PushPinStandard.png" />-->
<Image Stretch="Fill" Source="{Binding Path=strPicturePushpinFournisseur, Source={StaticResource myParamObject}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Width" Value="64" />
<Setter Property="Height" Value="64" />
</Style>
</ResourceDictionary>
strPicturePushpinFournisseur is string in CParametres. This string contain the picture paths.
Actually, the image don't display and it's related to my bad binding.
Anyone could help me please ?
Any ideas ?
Thanks a lot :)
You can do some thing like this:
To put the object in the resource dictionary for making it available to the rest of the application
<Application x:Class="SomeNameSpace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:t="clr-namespace:SomeNameSpace.NameSpaceForT"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="View/DictionaryResources/MainResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<t:CParametres x:Key="myParamObject"/>
</ResourceDictionary>
</Application.Resources>
</Application>
Make a binding to any object's property (This is a sample):
<Window x:Class="SomeNameSpace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:View="clr-namespace:SomeNameSpace.View"
Title="MainWindow"
DataContext="{Binding Path=strPicturePushpinFournisseur, Source={StaticResource myParamObject}}"
Height="350" Width="525">
...
EDIT
You can create the object in the App.xaml.cs file, and add contructor parameters in this way:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Resources.Add("myParamObject", new CParametres ("Param1", "Param2"));
}
}
And use it in this way:
<TextBlock Text="{Binding Path=strPicturePushpinFournisseur, Source={StaticResource myParamObject}}"></TextBlock>
Hope it helps...
I'm trying to bind controlTemplate to in generic.xaml.My controlTemplate has converter in it.While binding,its throwing an exception as Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.
In MyView.cs
templateString = #"<ControlTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
<Canvas><Polygon Points=""{Binding Size,Converter={StaticResource SizeConverter}}"" Fill=""red""/></Canvas>
</ControlTemplate>";
this.Template = XamlReader.Load(new System.Xml.XmlTextReader(new StringReader(templateString ))) as ControlTemplate;
In generic.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:MySample"
xmlns:vsm="clr-namespace:System.Windows;assembly=PresentationFramework"
xmlns:srcview="clr-namespace:MySample.Views"
xmlns:converters="clr-namespace:MySample.Converters"
>
<converters:SizeConverter x:Key="SizeConverter" />
<Style TargetType="{x:Type srcview:MyView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type srcview:MyView}">
<Canvas>
<ContentControl Template="{TemplateBinding Template}" Name="contentControl" >
</ContentControl>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
How to fix this issue??
One normally gets this problem when the static resources are not defined before referencing them.
For a test, try reading an xaml usercontrol with a static resource defined in the resources section of the xaml. If that works then you know the problem is not with referencing the converter, but rather when and were it is defined.
A faster way to ensure that the converter is actually being loaded is to put it in the app.xaml. This will ensure that the resource dictionary is loaded at startup. Here follows an example:
<Application x:Class="TeslaFrame.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:metro="http://schemas.codeplex.com/elysium"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Elysium;component/Themes/Generic.xaml"/>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="globalBoolToVisConverter" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>