Loading a XAML file related to a control programmatically?
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I'm trying to have a custom WPF control whose content is defined in XAML but avoiding the use of a UserControl
. This is because a UserControl makes it impossible to add x:Name
to its content: https://stackoverflow.com/questions/751325/how-to-create-a-wpf-usercontrol-with-named-content/3413382
My files are laid out like this:
.
â App.config
â App.xaml
â App.xaml.cs
â MainWindow.xaml
â MainWindow.xaml.cs
â WpfScratch.csproj
âÂÂ
âÂÂâÂÂâÂÂâÂÂbin
â âÂÂâÂÂâÂÂâÂÂDebug
â â â WpfScratch.exe
â â â WpfScratch.exe.config
â â â WpfScratch.pdb
â â âÂÂ
â â âÂÂâÂÂâÂÂâÂÂControls
â âÂÂâÂÂâÂÂâÂÂRelease
âÂÂâÂÂâÂÂâÂÂControls
. MyPanel.cs
. MyPanel.xaml
and the source of the relevant ones is:
MyPanel.cs
public class MyPanel : Control
static MyPanel()
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyPanel), new FrameworkPropertyMetadata(typeof(MyPanel)));
public MyPanel()
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
public static readonly DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Body
get => GetValue(BodyProperty);
set => SetValue(BodyProperty, value);
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register("Footer", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Footer
get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
MyPanel.xaml
<ControlTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfScratch.Controls"
TargetType="local:MyPanel" >
<DockPanel LastChildFill="True" x:Name="Content">
<Border BorderThickness="2"
BorderBrush="Aqua"
DockPanel.Dock="Bottom">
<ContentPresenter x:Name="Footer"
Content="Binding Footer, RelativeSource=RelativeSource TemplatedParent"
Margin="0, 10" />
</Border>
<Border BorderThickness="2"
BorderBrush="Magenta">
<ContentPresenter x:Name="Body"
Content="Binding Body, RelativeSource=RelativeSource TemplatedParent" />
</Border>
</DockPanel>
</ControlTemplate>
MainWindow.xaml
<Window x:Class="WpfScratch.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:WpfScratch"
xmlns:controls="clr-namespace:WpfScratch.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<controls:MyPanel x:Name="HelloWorldPanel">
<controls:MyPanel.Body>
<Label x:Name="HelloLabel">Hello!</Label>
</controls:MyPanel.Body>
<controls:MyPanel.Footer>
<Label x:Name="WorldLabel">World!</Label>
</controls:MyPanel.Footer>
</controls:MyPanel>
</Window>
My main concern is the loading of the XAML file, i.e.:
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
- Is
Application.Load()
the way to go? UWP seems to deprecate it in favour ofXAMLReader.Load()
, but I'm not sure how I would get the correct stream for that. I tried digging into the sources of Application.LoadComponent and there's some logic involved with processing pack URIs - The URI is a hardcoded mouthful and seems not very resilient to refactoring. Is there a terse way of saying "hey my XAML file is right next to this one"?
c# wpf xaml
add a comment |Â
up vote
4
down vote
favorite
I'm trying to have a custom WPF control whose content is defined in XAML but avoiding the use of a UserControl
. This is because a UserControl makes it impossible to add x:Name
to its content: https://stackoverflow.com/questions/751325/how-to-create-a-wpf-usercontrol-with-named-content/3413382
My files are laid out like this:
.
â App.config
â App.xaml
â App.xaml.cs
â MainWindow.xaml
â MainWindow.xaml.cs
â WpfScratch.csproj
âÂÂ
âÂÂâÂÂâÂÂâÂÂbin
â âÂÂâÂÂâÂÂâÂÂDebug
â â â WpfScratch.exe
â â â WpfScratch.exe.config
â â â WpfScratch.pdb
â â âÂÂ
â â âÂÂâÂÂâÂÂâÂÂControls
â âÂÂâÂÂâÂÂâÂÂRelease
âÂÂâÂÂâÂÂâÂÂControls
. MyPanel.cs
. MyPanel.xaml
and the source of the relevant ones is:
MyPanel.cs
public class MyPanel : Control
static MyPanel()
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyPanel), new FrameworkPropertyMetadata(typeof(MyPanel)));
public MyPanel()
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
public static readonly DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Body
get => GetValue(BodyProperty);
set => SetValue(BodyProperty, value);
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register("Footer", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Footer
get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
MyPanel.xaml
<ControlTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfScratch.Controls"
TargetType="local:MyPanel" >
<DockPanel LastChildFill="True" x:Name="Content">
<Border BorderThickness="2"
BorderBrush="Aqua"
DockPanel.Dock="Bottom">
<ContentPresenter x:Name="Footer"
Content="Binding Footer, RelativeSource=RelativeSource TemplatedParent"
Margin="0, 10" />
</Border>
<Border BorderThickness="2"
BorderBrush="Magenta">
<ContentPresenter x:Name="Body"
Content="Binding Body, RelativeSource=RelativeSource TemplatedParent" />
</Border>
</DockPanel>
</ControlTemplate>
MainWindow.xaml
<Window x:Class="WpfScratch.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:WpfScratch"
xmlns:controls="clr-namespace:WpfScratch.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<controls:MyPanel x:Name="HelloWorldPanel">
<controls:MyPanel.Body>
<Label x:Name="HelloLabel">Hello!</Label>
</controls:MyPanel.Body>
<controls:MyPanel.Footer>
<Label x:Name="WorldLabel">World!</Label>
</controls:MyPanel.Footer>
</controls:MyPanel>
</Window>
My main concern is the loading of the XAML file, i.e.:
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
- Is
Application.Load()
the way to go? UWP seems to deprecate it in favour ofXAMLReader.Load()
, but I'm not sure how I would get the correct stream for that. I tried digging into the sources of Application.LoadComponent and there's some logic involved with processing pack URIs - The URI is a hardcoded mouthful and seems not very resilient to refactoring. Is there a terse way of saying "hey my XAML file is right next to this one"?
c# wpf xaml
I can't see where the name is being used. Am I overlooking something? Is it used in code which you haven't included in the question?
â Peter Taylor
Jul 30 at 11:01
@Peter - which name?
â millimoose
Jul 30 at 11:03
Any of them. You say that the reason for avoiding UserControl is that it prevents you using names, but I can't see why any of the names in the code is actually necessary. All of the binding seems to be to properties rather than elements.
â Peter Taylor
Jul 30 at 11:06
@PeterTaylor - code clarity and being able to navigate the visual tree easier when debugging
â millimoose
Jul 30 at 11:07
And yes, obviously it would be useful if I needed to identify the control in codebehind, but thatâÂÂs not my use case yet and I was motivated by the previous reasons to look into this, since itâÂÂs a vexing restriction with a confusing error message
â millimoose
Jul 30 at 11:08
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I'm trying to have a custom WPF control whose content is defined in XAML but avoiding the use of a UserControl
. This is because a UserControl makes it impossible to add x:Name
to its content: https://stackoverflow.com/questions/751325/how-to-create-a-wpf-usercontrol-with-named-content/3413382
My files are laid out like this:
.
â App.config
â App.xaml
â App.xaml.cs
â MainWindow.xaml
â MainWindow.xaml.cs
â WpfScratch.csproj
âÂÂ
âÂÂâÂÂâÂÂâÂÂbin
â âÂÂâÂÂâÂÂâÂÂDebug
â â â WpfScratch.exe
â â â WpfScratch.exe.config
â â â WpfScratch.pdb
â â âÂÂ
â â âÂÂâÂÂâÂÂâÂÂControls
â âÂÂâÂÂâÂÂâÂÂRelease
âÂÂâÂÂâÂÂâÂÂControls
. MyPanel.cs
. MyPanel.xaml
and the source of the relevant ones is:
MyPanel.cs
public class MyPanel : Control
static MyPanel()
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyPanel), new FrameworkPropertyMetadata(typeof(MyPanel)));
public MyPanel()
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
public static readonly DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Body
get => GetValue(BodyProperty);
set => SetValue(BodyProperty, value);
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register("Footer", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Footer
get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
MyPanel.xaml
<ControlTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfScratch.Controls"
TargetType="local:MyPanel" >
<DockPanel LastChildFill="True" x:Name="Content">
<Border BorderThickness="2"
BorderBrush="Aqua"
DockPanel.Dock="Bottom">
<ContentPresenter x:Name="Footer"
Content="Binding Footer, RelativeSource=RelativeSource TemplatedParent"
Margin="0, 10" />
</Border>
<Border BorderThickness="2"
BorderBrush="Magenta">
<ContentPresenter x:Name="Body"
Content="Binding Body, RelativeSource=RelativeSource TemplatedParent" />
</Border>
</DockPanel>
</ControlTemplate>
MainWindow.xaml
<Window x:Class="WpfScratch.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:WpfScratch"
xmlns:controls="clr-namespace:WpfScratch.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<controls:MyPanel x:Name="HelloWorldPanel">
<controls:MyPanel.Body>
<Label x:Name="HelloLabel">Hello!</Label>
</controls:MyPanel.Body>
<controls:MyPanel.Footer>
<Label x:Name="WorldLabel">World!</Label>
</controls:MyPanel.Footer>
</controls:MyPanel>
</Window>
My main concern is the loading of the XAML file, i.e.:
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
- Is
Application.Load()
the way to go? UWP seems to deprecate it in favour ofXAMLReader.Load()
, but I'm not sure how I would get the correct stream for that. I tried digging into the sources of Application.LoadComponent and there's some logic involved with processing pack URIs - The URI is a hardcoded mouthful and seems not very resilient to refactoring. Is there a terse way of saying "hey my XAML file is right next to this one"?
c# wpf xaml
I'm trying to have a custom WPF control whose content is defined in XAML but avoiding the use of a UserControl
. This is because a UserControl makes it impossible to add x:Name
to its content: https://stackoverflow.com/questions/751325/how-to-create-a-wpf-usercontrol-with-named-content/3413382
My files are laid out like this:
.
â App.config
â App.xaml
â App.xaml.cs
â MainWindow.xaml
â MainWindow.xaml.cs
â WpfScratch.csproj
âÂÂ
âÂÂâÂÂâÂÂâÂÂbin
â âÂÂâÂÂâÂÂâÂÂDebug
â â â WpfScratch.exe
â â â WpfScratch.exe.config
â â â WpfScratch.pdb
â â âÂÂ
â â âÂÂâÂÂâÂÂâÂÂControls
â âÂÂâÂÂâÂÂâÂÂRelease
âÂÂâÂÂâÂÂâÂÂControls
. MyPanel.cs
. MyPanel.xaml
and the source of the relevant ones is:
MyPanel.cs
public class MyPanel : Control
static MyPanel()
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyPanel), new FrameworkPropertyMetadata(typeof(MyPanel)));
public MyPanel()
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
public static readonly DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Body
get => GetValue(BodyProperty);
set => SetValue(BodyProperty, value);
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register("Footer", typeof(object), typeof(MyPanel), new PropertyMetadata(default(object)));
public object Footer
get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
MyPanel.xaml
<ControlTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfScratch.Controls"
TargetType="local:MyPanel" >
<DockPanel LastChildFill="True" x:Name="Content">
<Border BorderThickness="2"
BorderBrush="Aqua"
DockPanel.Dock="Bottom">
<ContentPresenter x:Name="Footer"
Content="Binding Footer, RelativeSource=RelativeSource TemplatedParent"
Margin="0, 10" />
</Border>
<Border BorderThickness="2"
BorderBrush="Magenta">
<ContentPresenter x:Name="Body"
Content="Binding Body, RelativeSource=RelativeSource TemplatedParent" />
</Border>
</DockPanel>
</ControlTemplate>
MainWindow.xaml
<Window x:Class="WpfScratch.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:WpfScratch"
xmlns:controls="clr-namespace:WpfScratch.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<controls:MyPanel x:Name="HelloWorldPanel">
<controls:MyPanel.Body>
<Label x:Name="HelloLabel">Hello!</Label>
</controls:MyPanel.Body>
<controls:MyPanel.Footer>
<Label x:Name="WorldLabel">World!</Label>
</controls:MyPanel.Footer>
</controls:MyPanel>
</Window>
My main concern is the loading of the XAML file, i.e.:
var templateUri = new Uri("/WpfScratch;component/Controls/MyPanel.xaml", UriKind.Relative);
Template = (ControlTemplate) Application.LoadComponent(templateUri);
- Is
Application.Load()
the way to go? UWP seems to deprecate it in favour ofXAMLReader.Load()
, but I'm not sure how I would get the correct stream for that. I tried digging into the sources of Application.LoadComponent and there's some logic involved with processing pack URIs - The URI is a hardcoded mouthful and seems not very resilient to refactoring. Is there a terse way of saying "hey my XAML file is right next to this one"?
c# wpf xaml
asked Jul 30 at 8:51
millimoose
25827
25827
I can't see where the name is being used. Am I overlooking something? Is it used in code which you haven't included in the question?
â Peter Taylor
Jul 30 at 11:01
@Peter - which name?
â millimoose
Jul 30 at 11:03
Any of them. You say that the reason for avoiding UserControl is that it prevents you using names, but I can't see why any of the names in the code is actually necessary. All of the binding seems to be to properties rather than elements.
â Peter Taylor
Jul 30 at 11:06
@PeterTaylor - code clarity and being able to navigate the visual tree easier when debugging
â millimoose
Jul 30 at 11:07
And yes, obviously it would be useful if I needed to identify the control in codebehind, but thatâÂÂs not my use case yet and I was motivated by the previous reasons to look into this, since itâÂÂs a vexing restriction with a confusing error message
â millimoose
Jul 30 at 11:08
add a comment |Â
I can't see where the name is being used. Am I overlooking something? Is it used in code which you haven't included in the question?
â Peter Taylor
Jul 30 at 11:01
@Peter - which name?
â millimoose
Jul 30 at 11:03
Any of them. You say that the reason for avoiding UserControl is that it prevents you using names, but I can't see why any of the names in the code is actually necessary. All of the binding seems to be to properties rather than elements.
â Peter Taylor
Jul 30 at 11:06
@PeterTaylor - code clarity and being able to navigate the visual tree easier when debugging
â millimoose
Jul 30 at 11:07
And yes, obviously it would be useful if I needed to identify the control in codebehind, but thatâÂÂs not my use case yet and I was motivated by the previous reasons to look into this, since itâÂÂs a vexing restriction with a confusing error message
â millimoose
Jul 30 at 11:08
I can't see where the name is being used. Am I overlooking something? Is it used in code which you haven't included in the question?
â Peter Taylor
Jul 30 at 11:01
I can't see where the name is being used. Am I overlooking something? Is it used in code which you haven't included in the question?
â Peter Taylor
Jul 30 at 11:01
@Peter - which name?
â millimoose
Jul 30 at 11:03
@Peter - which name?
â millimoose
Jul 30 at 11:03
Any of them. You say that the reason for avoiding UserControl is that it prevents you using names, but I can't see why any of the names in the code is actually necessary. All of the binding seems to be to properties rather than elements.
â Peter Taylor
Jul 30 at 11:06
Any of them. You say that the reason for avoiding UserControl is that it prevents you using names, but I can't see why any of the names in the code is actually necessary. All of the binding seems to be to properties rather than elements.
â Peter Taylor
Jul 30 at 11:06
@PeterTaylor - code clarity and being able to navigate the visual tree easier when debugging
â millimoose
Jul 30 at 11:07
@PeterTaylor - code clarity and being able to navigate the visual tree easier when debugging
â millimoose
Jul 30 at 11:07
And yes, obviously it would be useful if I needed to identify the control in codebehind, but thatâÂÂs not my use case yet and I was motivated by the previous reasons to look into this, since itâÂÂs a vexing restriction with a confusing error message
â millimoose
Jul 30 at 11:08
And yes, obviously it would be useful if I needed to identify the control in codebehind, but thatâÂÂs not my use case yet and I was motivated by the previous reasons to look into this, since itâÂÂs a vexing restriction with a confusing error message
â millimoose
Jul 30 at 11:08
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
5
down vote
accepted
The conventional way of attaching default template to custom control is to specify default style inside a special resource dictionary. For this approach to work three conditions should be met:
1) Resource dictionary should be located at Themes/Generic.xaml
. There you should place a default style for your custom control (that in turn should set Template
property to default value).
2) Your AssemblyInfo.cs
file should contain ThemeInfoAttribute
.
3) Your custom control should override default style key inside a static constructor, using DefaultStyleKeyProperty.OverrideMetadata
method.
Alternatively, if you are not planning on reusing your custom control, you can just drop the default style into App.xaml
resources and avoid above shenanigans.
For more info see: https://michaelscodingspot.com/2016/12/24/explicit-implicit-and-default-styles-in-wpf/
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
2
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary insideApp.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.
â Nikita B
Jul 30 at 11:17
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
The conventional way of attaching default template to custom control is to specify default style inside a special resource dictionary. For this approach to work three conditions should be met:
1) Resource dictionary should be located at Themes/Generic.xaml
. There you should place a default style for your custom control (that in turn should set Template
property to default value).
2) Your AssemblyInfo.cs
file should contain ThemeInfoAttribute
.
3) Your custom control should override default style key inside a static constructor, using DefaultStyleKeyProperty.OverrideMetadata
method.
Alternatively, if you are not planning on reusing your custom control, you can just drop the default style into App.xaml
resources and avoid above shenanigans.
For more info see: https://michaelscodingspot.com/2016/12/24/explicit-implicit-and-default-styles-in-wpf/
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
2
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary insideApp.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.
â Nikita B
Jul 30 at 11:17
add a comment |Â
up vote
5
down vote
accepted
The conventional way of attaching default template to custom control is to specify default style inside a special resource dictionary. For this approach to work three conditions should be met:
1) Resource dictionary should be located at Themes/Generic.xaml
. There you should place a default style for your custom control (that in turn should set Template
property to default value).
2) Your AssemblyInfo.cs
file should contain ThemeInfoAttribute
.
3) Your custom control should override default style key inside a static constructor, using DefaultStyleKeyProperty.OverrideMetadata
method.
Alternatively, if you are not planning on reusing your custom control, you can just drop the default style into App.xaml
resources and avoid above shenanigans.
For more info see: https://michaelscodingspot.com/2016/12/24/explicit-implicit-and-default-styles-in-wpf/
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
2
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary insideApp.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.
â Nikita B
Jul 30 at 11:17
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
The conventional way of attaching default template to custom control is to specify default style inside a special resource dictionary. For this approach to work three conditions should be met:
1) Resource dictionary should be located at Themes/Generic.xaml
. There you should place a default style for your custom control (that in turn should set Template
property to default value).
2) Your AssemblyInfo.cs
file should contain ThemeInfoAttribute
.
3) Your custom control should override default style key inside a static constructor, using DefaultStyleKeyProperty.OverrideMetadata
method.
Alternatively, if you are not planning on reusing your custom control, you can just drop the default style into App.xaml
resources and avoid above shenanigans.
For more info see: https://michaelscodingspot.com/2016/12/24/explicit-implicit-and-default-styles-in-wpf/
The conventional way of attaching default template to custom control is to specify default style inside a special resource dictionary. For this approach to work three conditions should be met:
1) Resource dictionary should be located at Themes/Generic.xaml
. There you should place a default style for your custom control (that in turn should set Template
property to default value).
2) Your AssemblyInfo.cs
file should contain ThemeInfoAttribute
.
3) Your custom control should override default style key inside a static constructor, using DefaultStyleKeyProperty.OverrideMetadata
method.
Alternatively, if you are not planning on reusing your custom control, you can just drop the default style into App.xaml
resources and avoid above shenanigans.
For more info see: https://michaelscodingspot.com/2016/12/24/explicit-implicit-and-default-styles-in-wpf/
answered Jul 30 at 10:51
Nikita B
12.3k11551
12.3k11551
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
2
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary insideApp.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.
â Nikita B
Jul 30 at 11:17
add a comment |Â
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
2
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary insideApp.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.
â Nikita B
Jul 30 at 11:17
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
Will this work is this control is in a subproject thatâÂÂs referenced by the main appâÂÂs project in a solution? That is, is the theme tied to the assembly rather than the app itself?
â millimoose
Jul 30 at 11:06
2
2
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, the three points are for using it as a subproject. The line beginning "Alternatively" is the simpler approach which suffices if you just want to tie the theme to the app.
â Peter Taylor
Jul 30 at 11:07
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary inside
App.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.â Nikita B
Jul 30 at 11:17
@millimoose, yes, first approach will work "out of the box": you will be able to use your custom controls the same way you use default ones - just by referencing them in your xaml. Second approach will technically work as well, but you would have to manually specify path to resource dictionary inside
App.xaml
every time you create a new application that depends on your sub-project. For that reason I wouldn't recommend using it across different assemblies.â Nikita B
Jul 30 at 11:17
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200572%2floading-a-xaml-file-related-to-a-control-programmatically%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
I can't see where the name is being used. Am I overlooking something? Is it used in code which you haven't included in the question?
â Peter Taylor
Jul 30 at 11:01
@Peter - which name?
â millimoose
Jul 30 at 11:03
Any of them. You say that the reason for avoiding UserControl is that it prevents you using names, but I can't see why any of the names in the code is actually necessary. All of the binding seems to be to properties rather than elements.
â Peter Taylor
Jul 30 at 11:06
@PeterTaylor - code clarity and being able to navigate the visual tree easier when debugging
â millimoose
Jul 30 at 11:07
And yes, obviously it would be useful if I needed to identify the control in codebehind, but thatâÂÂs not my use case yet and I was motivated by the previous reasons to look into this, since itâÂÂs a vexing restriction with a confusing error message
â millimoose
Jul 30 at 11:08