I have Created one User control for WPF Like Windows 8 Password box Model.
My UserControl XAML Code -
<Grid.Resources>
<Style x:Key="ButtonWithoutHover" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="0"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Border BorderBrush="Black" BorderThickness="2" >
<DockPanel Canvas.Right="2" Canvas.Top="2">
<Button Style="{StaticResource ButtonWithoutHover}" Height="25" Width="20" BorderThickness="3" BorderBrush="White" DockPanel.Dock="Right" Background="CadetBlue" >
<Button.Content>
<Label Content="->" Foreground="White" />
</Button.Content>
</Button>
<TextBox Height="30" Width="180" FontSize="18" BorderThickness="0" Name="txtNumber" DockPanel.Dock="Left" >
</TextBox>
</DockPanel>
</Border>
Edit 1:
I have include this Usercontrol in My project. But at the time of Implementing UserControl in Wpf Application There is No Click Event for my UserControl. So I add Click="UserControl1_Click" to Xaml. But It through an Error
The property 'Click' does not exist in XML namespace
'clr-namespace:NumericTextbox;assembly=NumericTextbox'.
My Application Xaml Code-
<Window x:Class="NumericAppication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:NumText="clr-namespace:NumericTextbox;assembly=NumericTextbox"
Title="MainWindow" Height="350" Width="525">
<Grid>
<NumText:UserControl1 Width="120" Height="30" Click="UserControl1_Click" />
</Grid>
</Window>
You could have a Dependency Property on the UserControl that you bind to the Click event of the button.
EDIT:
In your UserControl you can have
public EventHandler MyProperty
{
get { return (EventHandler)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(EventHandler), typeof(ownerclass));
then in the XAML you have:
<button Click="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=MyProperty}" />
Although, I think that it is best practice to use ICommand instead of the event handler but the principle is the same.
may be this will help you
<Button Style="{StaticResource ButtonWithoutHover}" Height="25"
Width="20" BorderThickness="3" BorderBrush="White"
DockPanel.Dock="Right" Background="CadetBlue" Click="Button_Click">
<Button.Content>
<Label Content="->" Foreground="White" />
</Button.Content>
</Button>
You can create a command an make a command binding like this:
Create RoutedUiCommand command:
Class Command
{
Static RoutedUICommand ButtonClick = New RoutedUICommand("Buttonclick", "ButtonClick", TypeOf(Window))
}
Then in xaml
<Window.CommandBindings>
<CommandBinding Command="local:Command.ButtonClick" Executed="CommandBinding_ButtonClick" />
</Window.CommandBindings>
inside the method CommandBinding_ButtonClick you make the logic.
and finally add the command to the button:
<Button Style="{StaticResource ButtonWithoutHover}" Height="25" Width="20" BorderThickness="3" BorderBrush="White" DockPanel.Dock="Right" Background="CadetBlue" Command=local:Command.ButtonClick>
<Button.Content>
<Label Content="->" Foreground="White" />
</Button.Content>
</Button>
When you design your user control have you tried this on your button?
(remember to choose that edit template thing)
https://i-msdn.sec.s-msft.com/dynimg/IC616903.png
p.s. when I design user controls I always prefer to use blend.
As we have created the UserControl1.then after adding the Click event the UserControl1.Desginer.cs file will look like this.
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(180, 38);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// UserControl1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.button1);
this.Name = "UserControl1";
this.Size = new System.Drawing.Size(286, 95);
this.ResumeLayout(false);
}
and in the UserControl1.cs file will have the body of the Button click event
private void button1_Click(object sender, EventArgs e)
{
}
this may help you.Plz let me know
Related
So I've been playing around with creating a custom title bar using WPF and this is what I have
<!--Add the WindowChrome object-->
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="34" />
</WindowChrome.WindowChrome>
<Window.Resources>
<ResourceDictionary>
<Style x:Key="CaptionButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="LayoutRoot" Background="Transparent" Width="44" Height="30">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" FontFamily="Segoe MDL2 Assets" FontSize="10"
Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center"
RenderOptions.ClearTypeHint="Auto" TextOptions.TextRenderingMode="Aliased" TextOptions.TextFormattingMode="Display"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="LayoutRoot" Property="Background" Value="#E5E5E5"/>
<Setter TargetName="txt" Property="Foreground" Value="#000000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--Minimize-->
<Style x:Key="MinimizeButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value=""/>
</Style>
<!--Maximize-->
<Style x:Key="MaximizeButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value=""/>
</Style>
<!--Restore-->
<Style x:Key="RestoreButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value=""/>
</Style>
<!--Close-->
<Style x:Key="CloseButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value=""/>
</Style>
</ResourceDictionary>
</Window.Resources>
<!-- Title bar button commands -->
<Window.CommandBindings>
<CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Close" />
<CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Maximize" />
<CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Minimize" />
<CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Restore" />
</Window.CommandBindings>
<Border x:Name="MainWindowBorder" BorderBrush="LightCoral" BorderThickness="0" >
<Grid x:Name="parentContainer" Background="LightBlue">
<Grid.RowDefinitions>
<RowDefinition Height ="Auto"/>
<RowDefinition Height ="*"/>
</Grid.RowDefinitions>
<!--Window chrome-->
<Grid Grid.Row="0" Height="30" Background="#F999">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
<!--App icon-->
<Image Source="/Resources/watermelon.ico" Width="18" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Center" />
<TextBlock Text="Sweet App" FontFamily="Arial" Margin="4 3 0 0" />
</StackPanel>
<!--Caption buttons-->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<Button Style="{StaticResource MinimizeButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Minimize"
Command="{x:Static SystemCommands.MinimizeWindowCommand}"/>
<Button x:Name="RestoreButton" Visibility="Collapsed" Style="{StaticResource RestoreButtonStyle}"
Command="{x:Static SystemCommands.RestoreWindowCommand}" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Restore"/>
<Button x:Name="MaximizeButton" Visibility="Visible" Style="{StaticResource MaximizeButtonStyle}"
Command="{x:Static SystemCommands.MaximizeWindowCommand}" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Maximize" />
<Button Style="{StaticResource CloseButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Close"
Command="{x:Static SystemCommands.CloseWindowCommand}"/>
</StackPanel>
</Grid>
<!--App content-->
<Grid Grid.Row="1" x:Name="AppArea">
<Path Data="M50,0L100,50 50,100 0,50z" Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2" />
</Grid>
</Grid>
</Border>
And that works great!
However if I were to comment out this part
<Window.CommandBindings>
<CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Close" />
<CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Maximize" />
<CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Minimize" />
<CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Restore" />
</Window.CommandBindings>
Then when I hover over the buttons (Minimize, Maximize and Close) they don't change color anymore and there are no obvious errors presented to me. And as far as I know, it shouldn't change anything UI related since the actual trigger for changing the button background is already defined above in the Window.Resources
Why is this happening?
Here's the code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
StateChanged += MainWindowStateChangeRaised;
}
// Can execute
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
// Minimize
private void CommandBinding_Executed_Minimize(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MinimizeWindow(this);
}
// Maximize
private void CommandBinding_Executed_Maximize(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MaximizeWindow(this);
}
// Restore
private void CommandBinding_Executed_Restore(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.RestoreWindow(this);
}
// Close
private void CommandBinding_Executed_Close(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.CloseWindow(this);
}
// State change
private void MainWindowStateChangeRaised(object sender, EventArgs e)
{
if (WindowState == WindowState.Maximized)
{
MainWindowBorder.BorderThickness = new Thickness(8);
RestoreButton.Visibility = Visibility.Visible;
MaximizeButton.Visibility = Visibility.Collapsed;
}
else
{
MainWindowBorder.BorderThickness = new Thickness(0);
RestoreButton.Visibility = Visibility.Collapsed;
MaximizeButton.Visibility = Visibility.Visible;
}
}
}
I want my textbox to have a watermark style.
I have the code below which I got here https://stackoverflow.com/a/21672408/9928363
<Grid>
<TextBox Width="250" VerticalAlignment="Center" HorizontalAlignment="Left" x:Name="SearchTermTextBox" Margin="5"/>
<TextBlock IsHitTestVisible="False" Text="Enter Search Term Here" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchTermTextBox}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
I have lots of Textbox and I only want some of it to use the style but not all.
How will I do that?
There are a number of ways to add a watermark to a textbox, including replacing the ControlTemplate of your TextBox (as your question implies). However, replacing the ControlTemplate of the TextBox may not be ideal because in so doing you become responsible for drawing the entire control, including the border, styling different states etc. This is not too difficult (you can use Visual Studio or Espression Blend to copy the template from your current theme), but unless you do a lot of work you will lose the WPF feature of adapting the styling of common controls to the current Windows theme.
If you want a simple, re-usable, pure XAML approach that doesn't require changing the control template, then declaring a style resource using a VisualBrush is one effective approach.
See below, where we have 3 text boxes, the watermark style is applied to two of them. This style goes a little further than your example by removing the watermark when the textbox has the input focus.
<Window ...>
<Window.Resources>
<Style TargetType="TextBox" x:Key="Watermark">
<Style.Resources>
<VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Enter Search Term Here" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</DataTrigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBox Width="250" VerticalAlignment="Center" FontSize="20"
HorizontalAlignment="Left" Style="{StaticResource Watermark}"/>
<TextBox Width="250" VerticalAlignment="Center"
HorizontalAlignment="Left"/>
<TextBox Width="250" VerticalAlignment="Center"
HorizontalAlignment="Left" Style="{StaticResource Watermark}"/>
</StackPanel>
</Window>
If you need the watermark to react to different font sizes, you could make use of the Stretch property:-
<VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="Uniform">
<VisualBrush.Visual>
<Label Padding="2 1" Content="Enter Search Term Here" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
As stated in an earlier answer, sometimes it is preferable not to replace the ControlTemplate of the standard controls. So here's a method to create a watermark via an attached property, that keeps the existing control template intact. This has the advantage that you can set the watermark to any text, including setting it at runtime via data binding.
For demonstration the XAML will create 3 textboxes (see below). The bottom textbox has a watermark whose Text property is bound to the Text property of the top textbox, which demonstrates the dynamic nature of the watermark text. Typing a number into the second textbox will change the font size of the Text (and watermark) of the bottom textbox.
The above image is taken from Windows 10 standard theme. Here is is again after setting the Windows theme to High Contrast. As you can see the existing ControlTemplate (and color scheme) has been respected.
XAML
<Window x:Class="WpfApp2.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:behaviors="clr-namespace:WpfApp2.Behaviors"
mc:Ignorable="d"
Title="MainWindow" Height="250" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Watermark" Grid.Row="0"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="5"
x:Name="watermark" Width="250" HorizontalAlignment="Left" Text="enter search term here"/>
<Label Content="Font Size" Grid.Row="1"/>
<TextBox Grid.Row="1" Grid.Column="1" Margin="5"
x:Name="fontSize" Width="250" VerticalAlignment="Center" HorizontalAlignment="Left"
behaviors:TextBoxExtensions.Watermark="Enter a font size"/>
<Label Content="Result" Grid.Row="2"/>
<TextBox Grid.Row="2" Grid.Column="2" Margin="5"
Width="200" VerticalAlignment="Center" HorizontalAlignment="Left"
FontSize="{Binding Text, ElementName=fontSize}"
behaviors:TextBoxExtensions.Watermark="{Binding Path=Text, ElementName=watermark}" />
</Grid>
</Window>
TextBoxExtensions.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApp2.Behaviors
{
public class TextBoxExtensions
{
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
"Watermark",
typeof(string),
typeof(TextBoxExtensions),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, OnWatermarkTextChanged)
);
private static void OnWatermarkTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var tb = d as TextBox;
if (tb != null)
{
var textChangedHandler = new TextChangedEventHandler((s, ea) => ShowOrHideWatermark(s as TextBox));
var focusChangedHandler = new DependencyPropertyChangedEventHandler((s, ea) => ShowOrHideWatermark(s as TextBox));
var sizeChangedHandler = new SizeChangedEventHandler((s, ea) => ShowOrHideWatermark(s as TextBox));
if (string.IsNullOrEmpty(e.OldValue as string))
{
tb.TextChanged += textChangedHandler;
tb.IsKeyboardFocusedChanged += focusChangedHandler;
// We need SizeChanged events because the Background brush is sized according to the control size
tb.SizeChanged += sizeChangedHandler;
}
if (string.IsNullOrEmpty(e.NewValue as string))
{
tb.TextChanged -= textChangedHandler;
tb.IsKeyboardFocusedChanged -= focusChangedHandler;
tb.SizeChanged -= sizeChangedHandler;
}
ShowOrHideWatermark(tb);
}
}
public static string GetWatermark(DependencyObject element)
{
return (string)element.GetValue(WatermarkProperty);
}
public static void SetWatermark(DependencyObject element, string value)
{
element.SetValue(WatermarkProperty, value);
}
private static void ShowOrHideWatermark(TextBox tb)
{
// Restore TextBox background to style/theme value
tb.ClearValue(TextBox.BackgroundProperty);
if (string.IsNullOrEmpty(tb.Text) && !tb.IsKeyboardFocused)
{
var wm = GetWatermark(tb);
if (!string.IsNullOrEmpty(wm))
{
tb.Background = CreateTextBrush(wm, tb);
}
}
}
private static Brush CreateTextBrush(string text, TextBox tb)
{
Grid g = new Grid
{
Background = tb.Background,
Width = tb.ActualWidth,
Height = tb.ActualHeight
};
g.Children.Add(new Label
{
Padding = new Thickness(2,1,1,1),
FontSize = tb.FontSize,
FontFamily = tb.FontFamily,
Foreground = Brushes.LightGray,
Content = text
});
VisualBrush vb = new VisualBrush
{
Visual = g,
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Center,
};
return vb;
}
}
}
None of the watermark mechanisms is perfect for every scenario. This particular solution has the benefit of preserving the default theme, will use the font size and family of the TextBox, and will respect the background color set on the TextBox control via a style or theme. However it will not work correctly if you attempt to set the Background property of the TextBox directly in XAML as this value will be wiped out by the watermark.
I'm trying to create a download bar like chrome.
The issue I'm currently having is trying to bind the click event to the button's context menu within the listboxitem. When the context menuitem is clicked, it says the action is not found.
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Button BorderBrush="Transparent" BorderThickness="0" telerik:StyleManager.Theme="Windows8" Click="ButtonBase_OnClick">
<StackPanel Name="Panel" SnapsToDevicePixels="True"
Orientation="Horizontal" Margin="1 0"
Height="30">
<ContentControl Margin="0 0 10 0" Height="20">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource Icons.File}"></Setter>
</Style>
</ContentControl.Style>
</ContentControl>
<TextBlock Foreground="Black" Text="{Binding FileName}"
VerticalAlignment="Center"
TextAlignment="Center"
Margin="1 0 0 0"/>
<Button x:Name="ExpandButton" Background="Transparent" Click="ExpandButton_OnClick" BorderThickness="0" VerticalAlignment="Center" ContextMenuService.IsEnabled="false">
<Button.ContextMenu>
<ContextMenu x:Name="popup">
<MenuItem Header="Open" cal:Message.Attach="[Click] = [Open($this)]"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
<ContentControl ContentTemplate="{StaticResource Icons.ArrowUp}" Width="10" Height="10" Margin="2" VerticalAlignment="Center"/>
</Button>
<Rectangle Width="2" Fill="Gray" Margin="0 0 0 0"/>
</StackPanel>
</Button>
</ControlTemplate>
I could bind it behind code(xaml.cs) side of the application but I also lose track of what item is the context suppose to point to. To do that, i replaced caliburn's click event with a regular Click event. The SelectedItem and SelectedItems is null or empty, respectively.
private void MenuItem_OnClick(object sender, RoutedEventArgs e)
{
var originalSource = e.OriginalSource;
var selectedItem = FileListBox.SelectedItem;
var SelectedItems = FileListBox.SelectedItems;
}
Haven't tested but something along these lines should open the context menu on right or left click:
<Button x:Name="ExpandButton" Background="Transparent" Click="ContextMenu_Click" BorderThickness="0" VerticalAlignment="Center" ContextMenuService.IsEnabled="false">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu x:Name="popup" MenuItem.Click="menuItem_Click">
<MenuItem Header="Open" cal:Message.Attach="[Click] = [Open($this)]"></MenuItem>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
<ContentControl ContentTemplate="{StaticResource Icons.ArrowUp}" Width="10" Height="10" Margin="2" VerticalAlignment="Center"/>
</Button>
As for the code-behind, the following worked for me in my last tug with a similar issue:
DependencyObject mainDep = new DependencyObject();
private void ContextMenu_Click(object sender, RoutedEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is ListBoxItem))
{
dep = VisualTreeHelper.GetParent(dep);
}
mainDep = dep;
}
private void menuItem_Click(object sender, RoutedEventArgs e)
{
DependencyObject dep = mainDep;
if (dep is ListBoxItem)
{
...
DO your stuff here
...
}
}
Let me know how these work for you
I declare a style in xaml that I need to use and apply to a user control in code behind and when I use the same style twice the following error throws:
Element already has a logical parent. It must be detached from the old
parent before it is attached to a new one.
What am I doing wrong? I need to create multiple controls of the same user-control-type in code behind and apply one and the same Style to it.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
x:Class="MyChartControl.MainWindow"
Title="MainWindow" Height="655" Width="1020">
<Window.Resources>
<Style x:Key="SciChartSurfaceStyle" TargetType="{x:Type s:SciChartSurface}">
<Setter Property="XAxis">
<Setter.Value>
<s:DateTimeAxis Visibility="Visible"
TextFormatting="dd/MM/yyyy"
SubDayTextFormatting="dd/MM/yyyy HH:mm:ss.fff"
GrowBy="0.02, 0.02"/>
</Setter.Value>
</Setter>
<Setter Property="YAxis">
<Setter.Value>
<s:NumericAxis AxisAlignment="Right"
Visibility="Visible"
TextFormatting="{Binding YAxisFormatting}"
GrowBy="0.02, 0.02"
AutoRange="Always"/>
</Setter.Value>
</Setter>
<Setter Property="ChartModifier">
<Setter.Value>
<s:ModifierGroup>
<s:RubberBandXyZoomModifier IsAnimated = "False" IsXAxisOnly = "True" ExecuteOn = "MouseRightButton"/>
<s:ZoomPanModifier XyDirection="XYDirection" ClipModeX = "ClipAtExtents" ExecuteOn ="MouseLeftButton" />
<s:MouseWheelZoomModifier XyDirection = "XYDirection"/>
<s:ZoomExtentsModifier IsAnimated = "False" ExecuteOn = "MouseDoubleClick" />
<s:XAxisDragModifier DragMode = "Scale"/>
<s:CursorModifier SourceMode="AllSeries" UseInterpolation="True"/>
<s:LegendModifier ShowLegend="True" LegendPlacement ="Inside" GetLegendDataFor="AllSeries" Margin="10"/>
<!--<s:SeriesSelectionModifier ReceiveHandledEvents="True">
<s:SeriesSelectionModifier.SelectedSeriesStyle>
<Style TargetType="s:BaseRenderableSeries">
<Setter Property="SeriesColor" Value="White"/>
<Setter Property="PointMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<s:EllipsePointMarker Fill="#FF00DC" Stroke="White" Width="7" Height="7"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</s:SeriesSelectionModifier.SelectedSeriesStyle>
</s:SeriesSelectionModifier>-->
</s:ModifierGroup>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Background="Black">
<TextBlock Text="Dataseries Type:" Margin="5,0" VerticalAlignment="Center" FontSize="12" Foreground="White"/>
<ComboBox x:Name="ComboBox_ChooseSeriesType" MinWidth="140" Margin="5,3" VerticalContentAlignment="Center"/>
<TextBlock Text="Theme:" Margin="5,0" VerticalAlignment="Center" FontSize="12" Foreground="White"/>
<ComboBox x:Name="ComboBox_ChooseTheme" MinWidth="140" Margin="5,3" VerticalContentAlignment="Center"/>
</StackPanel>
<dxdo:LayoutGroup Grid.Row="1" x:Name="LayoutGroup" Orientation="Vertical">
<!--<dxdo:LayoutPanel Name="Panel1">
<s:SciChartSurface Name="Surface1" Style="{StaticResource SciChartSurfaceStyle}"></s:SciChartSurface>
</dxdo:LayoutPanel>-->
</dxdo:LayoutGroup>
</Grid>
And the code-behind method that retrieves the style and applies it:
private void TestSomeStuff()
{
var style = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface1 = new SciChartSurface() {Style = style};
var panel1 = new LayoutPanel(){Content=sciChartSurface1};
var style2 = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface2 = new SciChartSurface() {Style = style2};
var panel2 = new LayoutPanel() {Content = sciChartSurface2};
LayoutGroup.Add(panel1);
LayoutGroup.Add(panel2);
}
EDIT
Adding panel1 to LayoutGroup works just fine but the run-time error occurs as soon as I attempt to add panel2. Also, as long as do not inject style into a new instance of SciChartSurface it works just fine. The error pops up as soon as I inject the style into both new surfaces.
Do not set Style in code behind directly:
var style = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface1 = new SciChartSurface() {Style = style};
but with SetValue method:
var style = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface1 = new SciChartSurface();
sciChartSurface1.SetValue(StyleProperty, style);
I need a thumb control that can be sized using a mouse. When the user hovers the mouse over one of the ends a size cursor should be displayed and when the user clicks and drags the end of the control it will be re-sized.
How can that be achieved?
Here is one I made a while ago, it allows Move and Resize, but you can remove the Move logic and it should work fine (the style is still a bit messy, but it works pretty well)
Its based on ContentControl so you can add any Element inside and Move/Resize on a Canvas, It uses 3 Adorners, one for Resize, one for Move and one to display information (current size)
Here is a full working example if you want to test/use/modify/improve :)
Code:
namespace WpfApplication21
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class ResizeThumb : Thumb
{
public ResizeThumb()
{
DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
}
private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
Control designerItem = this.DataContext as Control;
if (designerItem != null)
{
double deltaVertical, deltaHorizontal;
switch (VerticalAlignment)
{
case VerticalAlignment.Bottom:
deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
designerItem.Height -= deltaVertical;
break;
case VerticalAlignment.Top:
deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical);
designerItem.Height -= deltaVertical;
break;
default:
break;
}
switch (HorizontalAlignment)
{
case HorizontalAlignment.Left:
deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal);
designerItem.Width -= deltaHorizontal;
break;
case HorizontalAlignment.Right:
deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
designerItem.Width -= deltaHorizontal;
break;
default:
break;
}
}
e.Handled = true;
}
}
public class MoveThumb : Thumb
{
public MoveThumb()
{
DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
}
private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
Control designerItem = this.DataContext as Control;
if (designerItem != null)
{
double left = Canvas.GetLeft(designerItem);
double top = Canvas.GetTop(designerItem);
Canvas.SetLeft(designerItem, left + e.HorizontalChange);
Canvas.SetTop(designerItem, top + e.VerticalChange);
}
}
}
public class SizeAdorner : Adorner
{
private Control chrome;
private VisualCollection visuals;
private ContentControl designerItem;
protected override int VisualChildrenCount
{
get
{
return this.visuals.Count;
}
}
public SizeAdorner(ContentControl designerItem)
: base(designerItem)
{
this.SnapsToDevicePixels = true;
this.designerItem = designerItem;
this.chrome = new Control();
this.chrome.DataContext = designerItem;
this.visuals = new VisualCollection(this);
this.visuals.Add(this.chrome);
}
protected override Visual GetVisualChild(int index)
{
return this.visuals[index];
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
this.chrome.Arrange(new Rect(new Point(0.0, 0.0), arrangeBounds));
return arrangeBounds;
}
}
}
Xaml:
<Window x:Class="WpfApplication21.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication21"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<local:MoveThumb Cursor="SizeAll">
<local:MoveThumb.Style>
<Style TargetType="{x:Type local:MoveThumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MoveThumb}">
<Rectangle Fill="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:MoveThumb.Style>
</local:MoveThumb>
<Control x:Name="resizer">
<Control.Style>
<Style TargetType="{x:Type Control}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<Grid>
<Grid Opacity="0" Margin="-3">
<local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
<local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
<local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
</Grid>
<Grid IsHitTestVisible="False" Opacity="1" Margin="-3">
<Grid.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Stroke" Value="#FFC8C8C8" />
<Setter Property="StrokeThickness" Value=".5" />
<Setter Property="Width" Value="7" />
<Setter Property="Height" Value="7" />
<Setter Property="Margin" Value="-2" />
<Setter Property="Fill" Value="Silver" />
</Style>
</Grid.Resources>
<Rectangle SnapsToDevicePixels="True" StrokeThickness="1" Margin="1" Stroke="Black" StrokeDashArray="4 4"/>
<Ellipse HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Ellipse HorizontalAlignment="Right" VerticalAlignment="Top"/>
<Ellipse HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
<Ellipse HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Control.Style>
</Control>
<Grid x:Name="sizeInfo" SnapsToDevicePixels="True">
<Path Stroke="Red" StrokeThickness="1" Height="10" VerticalAlignment="Bottom" Margin="-2,0,-2,-15" Stretch="Fill" Data="M0,0 0,10 M 0,5 100,5 M 100,0 100,10"/>
<TextBlock Text="{Binding Width}" Background="White" Padding="3,0,3,0" Foreground="Red" Margin="0,0,0,-18" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<Path Stroke="Red" StrokeThickness="1" Width="10" HorizontalAlignment="Right" Margin="0,-2,-15,-2" Stretch="Fill" Data="M5,0 5,100 M 0,0 10,0 M 0,100 10,100"/>
<TextBlock Text="{Binding Height}" Background="White" Foreground="Red" Padding="3,0,3,0" Margin="0,0,-18,0" HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90" CenterX="1" CenterY="0.5"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Grid>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="sizeInfo" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter TargetName="sizeInfo" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Canvas>
<ContentControl Width="183" Height="110" Canvas.Left="166" Canvas.Top="50" />
</Canvas>
</Window>
Result:
With content inside (Button)
Sorry the cursors do not show when using SnipTool