Dropshadow UserControl - wpf

I think doing the following is probably pretty common:
<Grid>
<Border>
<Border.Effect>
<DropShadowEffect/>
</Border.Effect>
</Border>
<SomeControl/>
</Grid>
Ok, I did that without the aid of the ide which I am admittedly lost without so forgive me if I forgot something but I think you get the point.
My question is, would it be possible to create a UserControl that would allow me to do this instead:
<DropShadowBorder>
<SomeControl/>
</DropShadowBorder>
If so, please do tell how.
EDIT: Just in case it's not immediately obvious, the point here is that I would usually put a border around my control but when I want to use a drop shadow I can't because I only want the border to have a drop shadow and not everything in it. So instead I have to create the border separately in the same grid space, but this is annoying because when I adjust margins and such on my control I have to go duplicate those changes on the border each time.

You can't do a user control (user control cannot have a content). You will have to create a custom control. I suggest you to create a custom control that derives from ContentControl.
The code of the custom control (default code !):
public class DropShadowBorder : ContentControl
{
static DropShadowBorder()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DropShadowBorder), new FrameworkPropertyMetadata(typeof(DropShadowBorder)));
}
}
Then define a default style for your control (in generic.xaml)
<Style TargetType="{x:Type local:DropShadowBorder}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DropShadowBorder}">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Border.Effect>
<DropShadowEffect />
</Border.Effect>
</Border>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

WPF Using Extended Toolkit Wizard - How to hide footer area?

I am using Extended Toolkit to create a wizard in WPF.
I choose PageType = WizardPageType.Blank.
I want to see an empty page, but I still see the footer area (I hide all buttons).
How can I hide this footer area?
There is no property to hide the footer area.
However, you can override the control template of the wizard. FYI, the default style is available on GitHub.
Assuming the namespace xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit", your "very basic" control template could look like this:
<Style TargetType="{x:Type xctk:Wizard}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type xctk:Wizard}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<Grid>
<ContentPresenter Content="{Binding CurrentPage, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Place this into Window.Resources or Application.Resources or wherever you like.

Semi-transparent background only in controls

I wonder if it's possible to make a new template (e.g. for a button), that have semi-transparent background? I can set the Background property and then choose my Opacity, but here lies the problem... When I set opacity of the background, each element added as a content of an element with set Opacity will be transparent, too. How to avoid it?
How about this? It's just a simple version. You will have to add the triggers etc by yourself.
<Style x:TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate x:TargetType="Button">
<Border BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Border Background="{TemplateBinding Background}"/>
</Grid>
</Border>
<ControlTemplate/>
</Setter.Value>
<Setter/>
</Style>
Now you can assign any background brush you want without influencing the content.

Setting TextTrimming (CharacterEllipsis) in DataGrid's Cell

I would like to apply TextTrimming property (CharacterEllipsis) to the text in WPF DataGrid cells.
I applied custom DataGridCell template as in this answer (code below) and it works well, except for the Hyperlink columns like the first one in the picture), which now are empty.
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Padding="3" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding Text}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I can see the difference in both column types in visual tree:
but don't understand how I can use this information to apply TextTrimming to TextBlock's columns of both type. Thanks for your time ;)
I finally ended up with the following solution (more like a workaround, but it works fine):
1) I assigned an x:Key to the style in question and applied it as a CellStyle to all DataGridTextColumns that should have their contents trimmed and ellipsisized whenever they don't fit
2) To apply ellipsis trimming in DataGridHyperlinkColumns, in App.xaml I added the following style:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextTrimming" Value="CharacterEllipsis"></Setter>
</Style>
which will apply to all implicitly generated TextBlocks (as described in CodeNaked's answer). This might seem a bit overkill, but I can't see much difference in rendering performance and Hyperlinks are now trimmed as expected.

How to bind Fill property to a custom property into a controltemplate

I have a button control which its template is stilyzed in an external resource Theme.xaml. Below the controltemplate definition:
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
<Grid x:Name="Grid">
<Border x:Name="Background" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="2,2,2,2" CornerRadius="2,2,2,2">
<Border x:Name="Hover" Background="{StaticResource HoverBrush}" CornerRadius="1,1,1,1" Height="Auto" Width="Auto" Opacity="0"/>
</Border>
<StackPanel Orientation="Horizontal" Margin="2,2,2,2">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" />
</StackPanel>
...
Now I added an item which is an ellipse that must be filled with red or green color (as a semaphore) depending on a custom property defined into my usercontrol:
<UserControl.Resources>
<ResourceDictionary Source="Themes/theme.xaml"/>
</UserControl.Resources>
<Grid>
<Button Click="Button_Click"></Button>
<Ellipse x:Name="ellipse1" Width="20" Height="20" Margin="5,40,45,5"></Ellipse>
</Grid>
and in the behind code I have:
private SolidColorBrush ButtonValue_;
public SolidColorBrush ButtonValue {
get { return ButtonValue_; }
set {
ButtonValue_ = value;
}
}
I'm trying to put into the CONTROLTEMPLATE this ellipse item, but i have some problems regarding how to BIND the Fill property of the ellipse with the ButtonValue custom property into the controlTemplate.
Any hints??
Thanks in advance
You can go to several directions:
Implement a custom control, that is your own class derived from an existing control (Button in your case). Add a dependency property (e.g. ButtonValue). Note - dependency property aren't standard .NET property - they have much more. Check out the following sample: http://msdn.microsoft.com/en-us/library/cc295235(v=expression.30).aspx (A custom button), or here: http://wpftutorial.net/HowToCreateACustomControl.html (A simpler sample, but without a property.
Have a data context for the control. Typically the data context is a separate class (a.k.a. the "View Model"), but if you aren't following the mvvm paradigm, it is OK the data context is self. Whatever data context you are using, it must derived from INotifyPropertyChanged, and it must file PropertyChanged event.
(Recommended!) Create a Control Template for CheckBox. When you come to think about it, logically your control is really a button with a binary state. Red/Green in your case, Checked/Unchecked for a CheckBox. So logically, you are looking for a checkbox, but you just want to present it differently.
So in your control template, draw the ellipse, and add a trigger for the IsChecked property:
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type CheckBox}">
<Grid>
... everything else in the control ...
<Ellipse x:Name="ellipse1" Width="20" Height="20" Margin="5,40,45,5" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="ellipse1" Property="Fill" Value="Red" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="ellipse1" Property="Fill" Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
This is a nice example for the difference between behavior and presentation of WPF.
While your control may look like a button, it behaves like a CheckBox, in the sense that it has two states.
EDIT: Use ToggleButton - this is the base class of CheckBox (and RadioButton), and it has exactly the functionality that you need, including the IsChecked property.
You have a couple of options:
1.The easiest one is to re-purpose an unused Brush or Color(with a converter) Button existing property:
<Window.Resources>
<ControlTemplate x:Key="repurposedProperty" TargetType="Button">
<Border Background="{TemplateBinding BorderBrush}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Window.Resources>
...
<Button Template="{StaticResource repurposedProperty}">Button</Button>
2.Other option is to define an attached property and use it in the ControlTemplate. On any Button that you apply the template to you have to set the attached property:
public static readonly DependencyProperty AttachedBackgroundProperty =
DependencyProperty.RegisterAttached("AttachedBackground", typeof (Brush), typeof (MainWindow),
new PropertyMetadata(default(Brush)));
public static void SetAttachedBackground(UIElement element, Brush value)
{
element.SetValue(AttachedBackgroundProperty, value);
}
public static Brush GetAttachedBackground(UIElement element)
{
return (Brush) element.GetValue(AttachedBackgroundProperty);
}
...
<
Window.Resources>
<ControlTemplate x:Key="attachedProperty" TargetType="Button">
<Border Background="{TemplateBinding WpfApplication1:MainWindow.AttachedBackground}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Window.Resources>
...
<Button Template="{StaticResource attachedProperty}">
<WpfApplication1:MainWindow.AttachedBackground>
<SolidColorBrush Color="Pink"></SolidColorBrush>
</WpfApplication1:MainWindow.AttachedBackground>
Button</Button>
PS: you can use a binding to set the value of the attached property.

Silverlight 4 - Mousewheel stops scrolling ScrollViewer when over contained RichTextBox

I have a Silverlight 4 out-of-browser application with a ScrollViewer that has several RichTextBoxes inside. The RichTextBoxes are only used for displaying text, and are never edited and never scroll.
However when the mouse is hovering over a RichTextBox the mousewheel event seems to not reach the ScrollViewer. Is there any way to overcome this limitation?
The reason a readonly RichTextBox doesn't scroll is because the default template for RichTextBox uses a ScrollViewer instead of a ContentControl. So to solve the problem, you need to create your own template for RichTextBox.
What I did was to create a copy of the RichTextBox template in Blend, and strip it down for the readonly case. This removes about 90% of the template. The following style/template remains:
<Style TargetType="c:RichTextBlock">
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid x:Name="RootElement">
<Border x:Name="Border" CornerRadius="0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
>
<ContentControl x:Name="ContentElement" IsTabStop="False" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Use this style/template for your readonly RichTextBox'es, and you should be good to go.
Goood luck,
Jim McCurdy
Face to Face Software and YinYangMoney

Resources