Why can't I see the control of my WPF custom control? - wpf

I have followed the solution of this question: how to have many wpf custom controls in the same library?
The problem now is that I can see the controls of my custom control when I add the custom control in my main view.
However, if I have the style in the generic.xaml file instead of the MyControl.xaml file, and only I have ona user control, it works.
The code of my MyControl.xaml is this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls.Calendario2">
<Style TargetType="{x:Type local:CalendarioMes2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CalendarioMes2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<TextBox Text="Prueba" BorderBrush="Black"/>
<Label Content="Prueba" BorderBrush="black"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And the generic.xaml has this code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls.Calendario2">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/CustomControls.Calendario2;component/ResourceDictionaries/CalendarioMes2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Why can't I see the textBox and the label?
Thanks.
EDIT: I have use the absolute path to the file:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="F:\Alvaro\ejemplos\Calendario\CustomControls\Themes\CalendarioMes2.xaml"/>
</ResourceDictionary.MergedDictionaries>
But know I have an error in the main window that say that I can create a type from the text. The error is in the CalendarioMes2.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls.Calendario2">
<Style TargetType="{x:Type local:CalendarioMes2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CalendarioMes2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<TextBox Text="Prueba" BorderBrush="Black"/>
<Label Content="Prueba" BorderBrush="black"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
In the line 7:
<Style TargetType="{x:Type local:CalendarioMes2}">
But compare my code with the code of the solution in the other thread, I see that I have the same line.
This is CalendarioMes2.cs
namespace CustomControls.Calendario2
{
public class CalendarioMes2 : Control
{
static CalendarioMes2()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarioMes2), new FrameworkPropertyMetadata(typeof(CalendarioMes2)));
}
}
}
EDIT: the source code is here: https://1drv.ms/u/s!AiTepLSbavZ0gRDvBPJgrxEIWS1U

Related

How could providing Parent Window as Pattern - WPF

Consider I have 4 Window on my project and I try to provide specific Closing button and one Title
How could I make a object of window and all of window use it as Pattern.
Here is Example of what we have for pattern window:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None" AllowsTransparency="True" >
<Grid>
<Button Content="Close" Height="40" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<TextBlock VerticalAlignment="Top" HorizontalAlignment="Center" X:Name="WindowTitle/>
</Grid>
</Window>
How could I use for all of my Window as pattern. Thanks
Actually, there is no need to write a parent window. You can use Style and Template instead. It's more convenient and is recommended by Microsoft WPF Team.
Write the code below into your App.xaml and you'll get the picture above:
<Application x:Class="Walterlv.Demo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
.........>
<Application.Resources>
<Style x:Key="Style.Window.Default" TargetType="Window">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Close" Height="40" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<TextBlock Grid.Row="0" VerticalAlignment="Top" HorizontalAlignment="Center"
Text="{TemplateBinding Title}"/>
<Border Grid.Row="1" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<!-- This is the container to host your Window.Content -->
<ContentPresenter/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
And you can use only one property Style to share such a "pattern":
<Window x:Class="Walterlv.Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Style="{StaticResource Style.Window.Default}">
</Window>
You can define different kinds of styles in the App.xaml file and select anyone in your XxxWindow.xaml you need.

How to set GroupStyle for custom control

I have created a custom control library project and did the followings:
The custom control is derived from ComboBox
Add a resource dictionary file rd.xaml under Themes folder
Define some styles in the rd.xaml file
<Style x:Key="GroupComboBoxStyle" TargetType="{x:Type local:GroupComboBox}">
<Setter Property="ItemContainerStyle" >
<Setter.Value>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="IsEnabled" Value="{Binding Available}"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:GroupComboBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" Width="150" Height="Auto" >
<!-- add scroll bar -->
</WrapPanel>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Item}" Width="40"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<CollectionViewSource x:Key="groupedData" Source="{Binding Items}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Category"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<Style x:Key="groupComboBoxItemStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="Width" Value="50" />
</Style>
<GroupStyle x:Key="groupStyle">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="2">
<TextBlock Text="{Binding Name}" HorizontalAlignment="Stretch" Background="YellowGreen"/>
</Border>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
Then I want to set the group style to my custom control at runtime
But the groupstyle cannot be found, how to get it from the resource dictionary file?
public GroupComboBox()
{
GroupStyle style = new GroupStyle();
// get the groupstyle
style.HeaderTemplate = (DataTemplate)this.FindResource("groupStyle");
this.GroupStyle.Add(style);
}
A WPF CustomControl is supposed to be lookless. This means, that the code should only contain the control's logic but nothing related to how it looks, styling, etc. This should all be done using the style which is created for you in the Generic.xaml.
Anyway, it is totally valid to wish for a green background in your header... I would suggest to create a bindable dependency property for a DefaultGroupStyle in your control. I've implemented and tested it and it does the trick:
The control GroupComboBox:
public class GroupComboBox : ComboBox
{
public static readonly DependencyProperty DefaultGroupStyleProperty =
DependencyProperty.Register("DefaultGroupStyle", typeof (GroupStyle), typeof (GroupComboBox), new PropertyMetadata(default(GroupStyle), OnDefaultGroupStyleChanged));
private static void OnDefaultGroupStyleChanged(DependencyObject s, DependencyPropertyChangedEventArgs a)
{
var c = (GroupComboBox) s;
if (a.NewValue == null) return;
if (c.GroupStyle.Count == 0)
c.GroupStyle.Add((GroupStyle) a.NewValue);
}
public GroupStyle DefaultGroupStyle
{
get { return (GroupStyle) GetValue(DefaultGroupStyleProperty); }
set { SetValue(DefaultGroupStyleProperty, value); }
}
static GroupComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(GroupComboBox), new FrameworkPropertyMetadata(typeof(GroupComboBox)));
}
}
and the styles in Generic.xaml (feel free to move the styles to another file but don't forget to merge it into Generic.xaml. Note that I removed the key on the default style for the ComboBox. It won't get applied automatically otherwise...
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary1">
<GroupStyle x:Key="GroupStyle">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="2">
<TextBlock Text="{Binding Name}" HorizontalAlignment="Stretch" Background="YellowGreen"/>
</Border>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
<Style TargetType="{x:Type local:GroupComboBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:GroupComboBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="DefaultGroupStyle" Value="{StaticResource GroupStyle}" />
</Style>
</ResourceDictionary>
Please let me know if this works for you and feel free to ask, if there's anything unclear.

TabItem - how to change template and leave default style?

I have the following code:
<Window x:Class="kkk.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="tabitemstyle" TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter x:Name="ContentSite" ContentSource="Header"></ContentPresenter>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl>
<TabItem Header="tab1" Style="{StaticResource tabitemstyle}"></TabItem>
<TabItem Header="tab1" Style="{StaticResource tabitemstyle}"></TabItem>
</TabControl>
</Grid>
</Window>
I want to preserve the default style of TabItem - I mean the padding/margins/BorderBrush/BorderThickness and so on... That is why I wrote BasedOn="...".
But it doesn't work - I thought it will render same as TabItem without any custom style but it doesn't - it just renders some text (by the ContentPresenter). The style doesn't get default properties values... How I can do it?
And I need the ControlTemplate inside my style...
You are overwriting the TabItem.Template, which is what tells WPF how to draw the object
If you want to create a template that is based on the default TabItem.Template, you can get the default template from MSDN and alter it to whatever you want.

Iterating through StaticResource loaded by ResourceDictionary

Given a resource dictionary loading some static resources into memory - is there any way to iterate through theResources loaded into memory? My silverlight application keeps telling me it cannot find a static resource. I wonder if I have a naming convention issue or somehting - was hoping iterating through the resources in memory would help diagnose any issue...
I have the following app.xaml
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Module1.MyApp">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FSSilverlightApp;component/TransitioningFrame.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
and content template:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="TransitioningFrame" TargetType="navigation:Frame">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter Cursor="{TemplateBinding Cursor}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</ResourceDictionary>
Resources defined in Application.Resources are implicitly available to all controls in the app, not sure about merged dictionaries. You can set a breakpoint in a control constructor and inspect this.Resources, this.Resources.MergedDictionaries, Application.Resources and Application.Resources.MergedDictionaries to see if your resource is there.
Also try to put the merged dictionaries in your control, see if that makes any difference:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FSSilverlightApp;component/TransitioningFrame.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<!--Use the style later in the same file-->
<navigation:Frame Style={StaticResource TransitioningFrame} />

Does anyone have a simple example of a UserControl with a single ContentPresenter?

So far, I have this:
<UserControl
x:Class="MyConcept.ExpanderPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Border
Style="{StaticResource Border_PanelStyle}"
CornerRadius="3" />
<ContentPresenter />
</Grid>
</UserControl>
Sample usage of this UserControl:
<nc:ExpanderPanel
Grid.Row="0">
<Expander
IsExpanded="True"
Header="NMT Users">
<StackPanel>
...
</StackPanel>
</Expander>
</nc:ExpanderPanel>
Discussion
If I run this, I see nothing. No content is presented, not even the border that is built into the UserControl.
I thought maybe I needed to make the ContentPresenter a dependency property, but I couldn't figure out how I would link the property to the ContentPresenter in the UserControl's XAML.
Can someone provide a simple example that shows how to build a UserControl (or some kind of custom control) with a single ContentPresenter?
ContentPresenters are main used in ControlTemplates and bound with a TemplateBinding to the ContentControl.Content.
from this site... a control template for a button that uses a ContentPresenter
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Rectangle Fill="{TemplateBinding Property=Background}" />
<ContentPresenter
Content="{TemplateBinding Property=ContentControl.Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources