Sending a parameter from user control that uses a custom control - c#

I want to pass a parameter from a User Control that uses a Custom Control, and use that on my Custom Control's cs. For example, if I had a Custom Control on a UserControl
In UserControl (e.g. ThisViewName.XAML):
<ctrl:PinWindowControl Tag="ThisViewName" Grid.Row="0"/>
Which pretty much just contains a button
Generic.xaml:
<Style TargetType="{x:Type local:PinWindowControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PinWindowControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Button Width="100" Height="100"></Button>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I get the Tag all the way to my PinWindowControl.cs file?

Assuming you created a DependencyProperty in your PinWindowControl:
You can access Tag using this.Tag. Your PinWindowControl is a partial class that is associated with your XAML.
public class PinWindowControl.cs : FrameworkElement
{
public PinWindowControl()
{
Debug.WriteLine(this.Tag);
}
}

Related

Event PreviewTextInput of textbox in a CustomControl . Please help me [duplicate]

This question already has answers here:
Is it possible to set code behind a resource dictionary in WPF for event handling?
(5 answers)
WPF Events in ResourceDictionary for a ControlTemplate
(1 answer)
Closed 1 year ago.
<Style TargetType="{x:Type local:CustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="1">
<Grid>
<TextBox x:Name="txtHour" Grid.Column="6" Text="00" Background="{TemplateBinding OpacityMask}" PreviewTextInput ="TextBox_PreviewTextInput"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I can't handle event PreviewTextInput in code behind.
Error 'ResourceDictionary' root element requires a x:Class attribute to support event handlers in the XAML file. Either remove the event handler for the PreviewTextInput event, or add a x:Class attribute to the root element.
public class CustomControl: Control
{
static CustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl), new FrameworkPropertyMetadata(typeof(CustomControl)));
}
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
MessageBox.Show("TEST");
}
}
This is my code behind.

Is it possible to apply MahApps’s TextBoxHelper to a ScrollViewer?

I’m building a WPF application in which there’s a TextBox. To apply rounded corners to it, here I read that I need to create a specific style using a ScrollViewer inside a Border. So far so good, but I want to apply the funcionalities of MahApps’ TextBoxHelper class, which lets you use stuff like:
<TextBox controls:TextboxHelper.Watermark="I’m a watermark"/>
to display a watermark inside the TextBox. The problem is that I don’t understand how to combine the style (using the advices in the article I linked to) with MahApps. I tried something like:
<Style TargetType="TextBox" x:Key="myKey">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" CornerRadius="10">
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
ctrl:TextboxHelper.Watermark="true"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
but the watermark doesn’t show.

Styling a Derived UserControl causes it to disappear

I have a control PaneBase, which derives from UserControl. There is no XAML, it's just a control. The UserControl type in question is the one from Catel, but I still observe this issue when using System.Windows.Controls.UserControl.
public class PaneBase : UserControl
{
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title",
typeof(string),
typeof(PaneBase),
new PropertyMetadata(default(string)));
public string Title
{
get => (string) GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
}
I have another control EquationPane which derives from PaneBase and does have XAML:
EquationPane.xaml
<local:PaneBase x:Class="EngineersToolkit.Windows.Views.Panes.EquationPane"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:catel="http://schemas.catelproject.com" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:EngineersToolkit.Windows.Views.Panes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Equation"
d:DataContext="{d:DesignData EquationPaneViewModel}" d:DesignHeight="450" d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<TextBox Width="150" Height="30"
Text="{Binding Equation, Mode=TwoWay}" />
</Grid>
</local:PaneBase>
EquationPane.xaml.cs
public partial class EquationPane
{
public EquationPane()
{
InitializeComponent();
DataContext = new EquationPaneViewModel();
}
}
All of this works so far, when I include an EquationPane in a window, then it shows up normally:
<Grid>
<panes:EquationPane Width="100" Height="100"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Aqua" />
</Grid>
It continues to work properly if I attempt to style the control:
<Style TargetType="{x:Type panes:EquationPane}">
<Setter Property="Background" Value="Red" />
</Style>
However, things begin to fall apart if I target the style to PaneBase instead. If I change TargetType to PaneBase, then the style is simply not applied. However, if I override the dependency property metadata in PaneBase like this:
static PaneBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PaneBase),
new FrameworkPropertyMetadata(
typeof(PaneBase)));
}
Then the control ceases to render at all, leaving me with a blank window. Why is this happening?
Why is this happening?
WPF controls are "lookless" which means that they have no appearance unless you define a template for them.
The following indicates that there is a default style defined for PaneBase in themes/generic.xaml:
static PaneBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PaneBase),
new FrameworkPropertyMetadata(
typeof(PaneBase)));
}
You should then define such a style:
<Style TargetType="local:PaneBase">
<Setter Property="Background" Value="Red" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type UserControl}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If you remove the static constructor in PanelBase it will inherit the template from the style of the UserControl base class.
If you then define a Style for PaneBase like this:
<Style TargetType="{x:Type local:PaneBase}">
<Setter Property="Background" Value="Red" />
</Style>
...it no longer has a template and that's why you don't see the control in your window.
Implicit Styles are not automatically applied to the derived types. To apply the style of PaneBase to EquationPane, you can do one of the following:
1.Write this on your EquationPane.xaml.cs
public EquationPane()
{
this.SetResourceReference(StyleProperty, typeof(PaneBase));
}
2.Explicitly provide the style where EquationPane is used
<panes:EquationPane Style="{DynamicResource {x:Type PaneBase}}"/>
3.Define a style that is basedon the parent style
<Style x:Key="{x:Type PaneBase}" TargetType="{x:Type PaneBase}">
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="{x:Type panes:EquationPane}" BasedOn="{StaticResource {x:Type PaneBase}}"/>

Adding Border for GridViewCell Programmatically

I'm trying to add a Thick Border around a certain column programmatically. I can change the Background property using identical methods but the border property won't change in anyway.
if (eligibleProperties.Contains(column.Header.ToString()))
{
Setter s1 = new Setter(GridViewCell.BorderThicknessProperty, new Thickness(7));
Setter s2 = new Setter(BorderBrushProperty, Brushes.Black);
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(s1);
st.Setters.Add(s2);
column.CellStyle = st;
}
Working code for Background change
if (eligibleProperties.Contains(column.Header.ToString()))
{
Setter s2 = new Setter(BackgroundProperty, Brushes.Black);
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(s2);
column.CellStyle = st;
}
Because of the default template structure of a Telerik GridViewCell, modifying the cell borders is actually more complicated than just setting the BorderThickness and BorderBrush properties.
You will need to modify the control template. Please refer to the following threads for more information about this.
How do I change border color in cell style selector: https://www.telerik.com/forums/how-do-i-change-border-color-in-cell-style-selector
Change the row border colour: https://www.telerik.com/forums/change-the-row-border-colour
I believe your best bet is to change the template of the cells for that column, you can even do it on the fly by setting the telerik:GridViewDataColumn.CellStyle of the column to this:
<Style TargetType="{x:Type telerik:GridViewCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="telerik:GridViewCell">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ToolTip="{TemplateBinding ToolTip}" VerticalAlignment="Center" Margin="3,0"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now your cells have the properties BorderThicknessand BorderBrush to work with. Like in this example below your cells will have a thick red border all around:
<telerik:GridViewDataColumn Header="MyColumn1" DataMemberBinding="{Binding MyColumn1Binding}" Width="150" >
<telerik:GridViewDataColumn.CellStyle>
<Style TargetType="{x:Type telerik:GridViewCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="telerik:GridViewCell">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ToolTip="{TemplateBinding ToolTip}" VerticalAlignment="Center" Margin="3,0"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Propert="BorderBrush" Value="Red" />
<Setter Propert="BorderThickness" Value="2,2,2,2" />
</Style>
</telerik:GridViewDataColumn.CellStyle>
</telerik:GridViewDataColumn
Using the thickness you could for example also hide the top and bottom borders. In the style you can also make use of Style.Triggers and define different border settings based on multiple DataTriggers.
I believe this offers much more flexibility than adding the borders programmatically. However, if you really want to do this in code then you can still define the template in XAML as in my first example which should make the setters from your code have affect.
And if this still doesn't seem sufficient enough, defining the template of the cell completely programmatically would be your next best bet. If you need help to translate the XAML to actual code just leave a comment, although I believe doing it in XAML is a lot better.

Click Button from Generic.xaml?

I am writing a custom control in Silverlight and I am having issues getting my Button to click to the Generic.xaml file. This does not work:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ScrollableTabControl">
<Button Grid.Row="0" Grid.Column="0" x:Name="ScrollLeft" Click="scrollLeft"><</Button>
</ControlTemplate>
</Setter.Value>
"ScrollLeft" is in my C# file.
However this does not work either:
var b = this.GetTemplateChild("ScrollLeft");
Debug.Assert(b != null);
Because no matter what I do, b always comes back null. I feel like there should be an easy way to assign the click method to this button, so what am I doing wrong?
EDIT: This is the method from my C# file:
public void scrollLeft(object sender, RoutedEventArgs e)
{
//var scroller = Application.Current.Resources["TabScroller"] as ScrollViewer;
//scroller.LineLeft();
}
You have to override the OnApplyTemplate() on your custom control class (C# File).
Like this.
public override void OnApplyTemplate()
{
Button btn = GetTemplateChild("ScrollLeft") as Button;
Debug.Assert(btn != null);
}
Also, you have to make one more change in the control template in Generic.Xaml like below.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Button Grid.Row="0" Grid.Column="0" x:Name="ScrollLeft"><</Button>
</Border>
</ControlTemplate>
</Setter.Value>
Note: I removed the Click event handler.
Although is it possible I recommend using Commands so the designer who replaces the template is free to pick other controls and events to bind the logic to.

Categories