Attach Dependency Property to User Control - c#

How to register DependencyProperty on Rectangle fill, so i can change the color
dynamically?
<UserControl.Resources>
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle Stroke="Black">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF48B6E4" Offset="0.013"/>
<GradientStop Color="#FF091D8D" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Button Style="{DynamicResource ButtonStyle1}"/>
<TextBlock
x:Name="NodeName"
x:FieldModifier="public"
Text="Property"
Margin="8"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextWrapping="Wrap"
TextAlignment="Center"
FontFamily="Segoe Print"
FontWeight="Bold"
Foreground="White"
FontSize="40"/>
</Grid>

Why don't you bind Fill to the Background property of the Button:
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle Stroke="Black" Fill="{TemplateBinding Background}" />
...
</Grid>
...
</ControlTemplate>
and then set Background like this:
<Button Style="{DynamicResource ButtonStyle1}">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF48B6E4" Offset="0.013"/>
<GradientStop Color="#FF091D8D" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
</Button>

If you have your own dependency property called MyProperty registered in your UserControl, you can bind it this way:
...
<Rectangle Stroke="Black" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Parent.Parent.MyProperty}" />
...
No other changes are needed.
This binds the Fill property to parent of parent of the control to which the style is assigned, in your case the UserControl itself.
Using this method you can not only bind it to properties of a UserControl, but also to other controls' properties.

I would create a dependency property on your YourUserControl view, something like this (I removed some of your markup for brevity):
<UserControl.Resources>
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle Stroke="Black" Fill="{TemplateBinding Background}">
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Grid x:Name="LayoutRoot">
<Button Style="{DynamicResource ButtonStyle1}" Background="{Binding DynamicColor}"/>
</Grid>
Then in YourUserControl.xaml.cs you could create your dependency property:
private My_ViewModel _viewModel
{
get { return this.DataContext as My_ViewModel; }
}
public LinearGradientBrush DynamicColor
{
get { return (string)GetValue(DynamicColorProperty); }
set { SetValue(DynamicColorProperty, value); }
}
public static readonly DependencyProperty DynamicColorProperty =
DependencyProperty.Register("DynamicColor", typeof(LinearGradientBrush), typeof(YourUserControl),
new PropertyMetadata(new PropertyChangedCallback(OnDynamicColorPropertyChanged)));
private static void OnDynamicColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((YourUserControl)d).OnTrackerInstanceChanged(e);
}
protected virtual void OnDynamicColorPropertyChanged(DependencyPropertyChangedEventArgs e)
{
this._viewModel.DynamicColor = e.NewValue;
}
public class My_ViewModel : INotifyPropertyChanged
{
public LinearGradientBrush DynamicColor
{
get { return dynamicColor; }
set
{
if(dynamicColor != value)
{
dynamicColor = value;
OnPropertyChanged("DynamicColor");
}
}
}
private LinearGradientBrush dynamicColor;
}
This approach gives you complete control over the DynamicColor property's value as well as allows you to be able to unit test the behavior effectively.

Related

Can't bind UserControl color property to ToggleButton background

I don't get it... I made a simple UserControl made of a togglebutton to open a popup containing a CustomControl, a colorpicker.
No problem to open/close the popup only if I write a color name for the toggle background color.
But, if I try to bind the UserControl Color property, to see the selected color when popup is closed, then the toggle button doesn't appear and is not working at all.
I must be missing a detail somwhere because I thought it was as simple as this :
<ToggleButton
x:Name="OpenColorPicker"
Style="{DynamicResource ToggleColorPickerStyle}"
Background="{Binding DataContext.SelectedColor, ElementName=ColorPickerWidget, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
Unfortunately not..
Here is the full XAML file :
<UserControl
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"
mc:Ignorable="d"
x:Class="CMiX.ColorSelector"
xmlns:colorPicker="clr-namespace:ColorPicker;assembly=ColorPicker"
xmlns:local="clr-namespace:CMiX"
Height="Auto" Width="Auto" d:DesignWidth="44.533" d:DesignHeight="24.933"
x:Name="ColorPickerWidget">
<UserControl.Resources>
<SolidColorBrush x:Key="BaseDarkColor" Color="#FF323232"/>
<local:ColorToBrushConverter x:Key="ColorToBrush"/>
<Style x:Key="ToggleColorPickerStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="FocusVisualStyle">
<Setter.Value>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Red"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<ToggleButton x:Name="OpenColorPicker" Style="{DynamicResource ToggleColorPickerStyle}" Background="{Binding DataContext.SelectedColor, ElementName=ColorPickerWidget, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Popup x:Name="PopupColorPicker" SnapsToDevicePixels="True" AllowsTransparency="True" IsOpen="{Binding IsChecked, ElementName=OpenColorPicker}" StaysOpen="True" Placement="Right">
<Border Margin="20, 20, 0, 20" Padding="5">
<colorPicker:ColorPicker x:Name="ColorPicker" Background="{StaticResource BaseDarkColor}" Width="420" Height="210" SelectedColor="{Binding DataContext.SelectedColor, ElementName=ColorPickerWidget, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<colorPicker:ColorPicker.Effect>
<DropShadowEffect BlurRadius="20" Opacity="1" Direction="0"/>
</colorPicker:ColorPicker.Effect>
</colorPicker:ColorPicker>
</Border>
</Popup>
</Grid>
The UserControl called ColorPickerWidget has this property :
public static readonly DependencyProperty
SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorSelector));
public Color SelectedColor
{
get { return (Color)GetValue(SelectedColorProperty); }
set { SetValue(SelectedColorProperty, value); }
}
Any idea ?
Thank you
EDIT __
I tried this :
<ToggleButton x:Name="OpenColorPicker" Background="{Binding SelectedColor, ElementName=ColorPicker, Converter={StaticResource ColorToBrush}}"/>
With this converter :
public class ColorToBrushConverter : IValueConverter
{
SolidColorBrush _red = new SolidColorBrush(),
_green = new SolidColorBrush(),
_blue = new SolidColorBrush(),
_alpha = new SolidColorBrush(),
_all = new SolidColorBrush();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var color = (Color)value;
switch ((string)parameter)
{
case "r":
_red.Color = Color.FromRgb(color.R, 0, 0);
return _red;
case "g":
_green.Color = Color.FromRgb(0, color.G, 0);
return _green;
case "b":
_blue.Color = Color.FromRgb(0, 0, color.B);
return _blue;
case "a":
_alpha.Color = Color.FromArgb(color.A,
128, 128, 128);
return _alpha;
case "all":
_all.Color = Color.FromArgb(color.A, color.R, color.G, color.B);
return _all;
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
But same problem, the button background gets not color.
There are a few problems with your binding to ToggleButton.Background. First, you're binding to the ColorPicker's DataContext.SelectedColor. The DataContext is the viewmodel. It's probably the same DataContext as the ToggleButton has. So you don't need to go to the ColorPicker to find it. But the ColorPicker isn't binding its SelectedColor to a viewmodel property anyway, so that's probably just a misunderstanding. Get rid of DataContext in that binding, it just sends the Binding off on a wild goose chase to nowhere.
Then you got the name wrong. You named the colorpicker "ColorPicker", but you told the binding to look for "ColorPickerWidget". And Mode=TwoWay is pointless because the ToggleButton can't change it's Background and send the color back to the color picker. But it's background isn't a color anyway; it's a Brush. So that couldn't possibly work.
And because it's expecting a Brush, you need a converter to convert color to brush. Brush properties in XAML are very disorienting because you can give them stuff like the string "Green" or "#882266aa", and they work. But that's because they're associated with a TypeConverter behind the scenes that converts those strings to Brush. But that doesn't work if you bind a Color value to the property. It's not intuitively obvious.
Does this binding work for ToggleButton.Background?
Background="{Binding SelectedColor, ElementName=ColorPicker, Converter={StaticResource ColorToBrush}}"

Get Set User Control Properties in WPF

Hello I have a problem accessing User Control Properties. My User Control Looks like this:
<UserControl.Resources>
<Style x:Key="CheckBoxStyle1" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="OnChecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="25"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnUnchecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.3000000" Value="1,1,1,1"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Border Name="Border">
<DockPanel x:Name="dockPanel">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center"/>
<Grid Width="50" x:Name="grid">
<TextBlock Text="ON" TextWrapping="Wrap" FontWeight="Bold" FontSize="12" HorizontalAlignment="Right" Margin="0,0,3,0"/>
<TextBlock HorizontalAlignment="Left" Margin="2,0,0,0" FontSize="12" FontWeight="Bold" Text="OFF" TextWrapping="Wrap"/>
<Border HorizontalAlignment="Left" x:Name="slider" Width="23" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3" RenderTransformOrigin="0.5,0.5" Margin="1,1,1,1">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Border.RenderTransform>
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FF4490FF" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF8AB4FF" Offset="1"/>
<GradientStop Color="#FFD1E2FF" Offset="0"/>
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<CheckBox x:Name="CheckBox1" HorizontalAlignment="Center"
Style="{DynamicResource CheckBoxStyle1}"
VerticalAlignment="Center"
Checked="CheckBox1_OnChecked"
Unchecked="CheckBox1_OnUnchecked"/>
</Grid>
And in the code behind(some of a great number of getters/setters):
public new Brush Background
{
get
{
var border = CheckBox1.Template.LoadContent() as Border;
return border == null ? Brushes.White : border.Background;
}
set
{
var border = CheckBox1.Template.LoadContent() as Border;
if (border == null) return;
border.Background = value;
}
}
public new Thickness BorderThickness
{
get
{
var border = CheckBox1.Template.LoadContent() as Border;
return border == null ? new Thickness(0) : border.BorderThickness;
}
set
{
var border = CheckBox1.Template.LoadContent() as Border;
if (border == null) return;
border.BorderThickness = value;
}
}
public new Brush BorderBrush
{
get
{
var border = CheckBox1.Template.LoadContent() as Border;
return border == null ? Brushes.Transparent : border.BorderBrush;
}
set
{
var border = CheckBox1.Template.LoadContent() as Border;
if (border == null) return;
border.BorderBrush = value;
}
}
And also i use it in another window like this(SliderOnOff is the name of my control):
<switch:SliderOnOff x:Name="SliderOnOff"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsEnabled="True"
Background="Green"
BorderThickness="10"
BorderBrush="HotPink"
IsChecked="True"
BorderRadius="5"
Checked="SliderOnOff_OnChecked"
UnChecked="SliderOnOff_OnUnChecked">
</switch:SliderOnOff>
I thought it works fine, because setting properties in xaml leaded to changing in properties of control.
BUT!!!!!!
When I try to change it programmatically ( Slider.Background = Brushes.HotPink; ), nothing happens, it doesnt change. Also this part of properties doesnt work at all(none in xaml, none in code):
public CornerRadius BorderRadius
{
get
{
var border = CheckBox1.Template.LoadContent() as Border;
return border == null ? new CornerRadius(0) : border.CornerRadius;
}
set
{
var border = CheckBox1.Template.LoadContent() as Border;
if (border == null) return;
border.CornerRadius = new CornerRadius(value.TopLeft,value.TopRight,value.BottomRight,value.BottomLeft);
}
}
Can you help me with it?
I think your ui hast to be informed about the changes.
Have a look at: http://www.codeproject.com/Articles/42536/List-vs-ObservableCollection-vs-INotifyPropertyCha
Your class must implement INotifyPropertyChanged, and within your "set" part you have to raise that event.
like:
public class MainViewModel : ViewModelBase, INotifyPropertyChanged
{
public KeyInfo SelectedKeyInfo
{
get
{
return _SelectedKeyInfo;
}
set
{
_SelectedKeyInfo = value;
OnPropertyChanged("SelectedKeyProducts");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}

Range Overlap Bar Chart

I am creating a Range Overlap Bar Chart that should display multi-value in a single bar and should change the color. In order to make what I want say clear I made a draw:
You can use Microsoft Chart Controls in Visual Studio toolbox. You will have to create multiple series as you want to show an overlap chart. This link will help you.
Here is some code...
DataSet dataSet;
ConnectionClass.GetInstance().connection_string = Properties.Settings.Default.MindMuscleConnectionString;
ConnectionClass.GetInstance().Sql = "Select Count(MemberInfo.memberName) as 'Members', CompetitionName as 'Competition' FROM MemberInfo, MemberBodyInfo, Competition WHERE MemberInfo.memberID = MemberBodyInfo.memberID AND MemberBodyInfo.weight >= Competition.CompetitionCategory and MemberBodyInfo.weight <= Competition.CompetitionCategory + 5 group by CompetitionName;";
dataSet = ConnectionClass.GetInstance().GetConnection;
chart1.Series["Series1"].Name = "Members";
chart1.Series["Members"].YValueMembers = "Members";
chart1.Series["Members"].XValueMember = "Competition";
chart1.Series.Add("Members2");
chart1.Series["Members2"].ChartType = SeriesChartType.StackedColumn;
chart1.Series["Members2"].IsValueShownAsLabel = true;
chart1.Series["Members2"].YValueMembers = "Members";
chart1.Series["Members2"].XValueMember = "Competition";
this.chart1.Titles.Add("Competition Participants"); // Set the chart title
chart1.Series["Members"].ChartType = SeriesChartType.StackedColumn;
chart1.Series["Members"].IsValueShownAsLabel = true; // To show chart value
chart1.DataSource = dataSet;
chart1.DataBind();
It will look like:
I have not actually created a new series from some different data... Both series are same here but I have just showed you an example. You will have to populate your series using your data.
Now if you change
chart1.Series["Members2"].ChartType = SeriesChartType.StackedColumn;
chart1.Series["Members"].ChartType = SeriesChartType.StackedColumn;
to
chart1.Series["Members2"].ChartType = SeriesChartType.StackedBar;
chart1.Series["Members"].ChartType = SeriesChartType.StackedBar;
The chart will look like exactly your drawing:
<UserControl x:Class="Budget.Summary.UserCtrlChartCategories"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/charts"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:local="clr-namespace:Budget.Summary"
mc:Ignorable="d" x:Name="userCtrl"
d:DesignHeight="450" d:DesignWidth="800"
Loaded="UserControl_Loaded"
Unloaded="UserControl_Unloaded" >
<UserControl.Resources>
<Style x:Key="MyExpenseBarDataPointStyle" TargetType="{x:Type chartingToolkit:BarDataPoint}">
<Setter Property="Height" Value="20" />
<Setter Property="Background" Value="Red" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5"/>
<Setter Property="RenderTransform" >
<Setter.Value>
<TransformGroup>
<ScaleTransform ScaleY="1.0"/>
<TranslateTransform Y="{Binding Path=ActualHeight, RelativeSource={RelativeSource AncestorType=chartingToolkit:BarDataPoint},Converter={StaticResource NegativeValueConverter}}" />
</TransformGroup>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BarDataPoint}">
<Border x:Name="Root"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Border.ToolTip>
<ContentControl Content="{TemplateBinding FormattedDependentValue}" />
</Border.ToolTip>
<Grid Background="{TemplateBinding Background}">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Color="#77FFFFFF" Offset="0" />
<GradientStop Color="Transparent" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Border BorderBrush="#CCFFFFFF" BorderThickness="1">
<Border BorderBrush="#77FFFFFF" BorderThickness="1" />
</Border>
<Rectangle x:Name="SelectionHighlight" Fill="Red" Opacity="0" />
<Rectangle x:Name="MouseOverHighlight" Fill="White" Opacity="0" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MyBudgetBarDataPointStyle"
TargetType="{x:Type chartingToolkit:BarDataPoint}">
<Setter Property="Background" Value="Green" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BarDataPoint}">
<Border x:Name="Root"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Border.ToolTip>
<ContentControl Content="{TemplateBinding FormattedDependentValue}" />
</Border.ToolTip>
<Grid Background="{TemplateBinding Background}">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Color="#77FFFFFF" Offset="0" />
<GradientStop Color="Transparent" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Border BorderBrush="#CCFFFFFF" BorderThickness="1">
<Border BorderBrush="#77FFFFFF" BorderThickness="1" />
</Border>
<Rectangle x:Name="SelectionHighlight" Fill="Red" Opacity="0" />
<Rectangle x:Name="MouseOverHighlight" Fill="White" Opacity="0" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid >
<!--https://www.c-sharpcorner.com/UploadFile/mahesh/bar-chart-in-wpf/-->
<chartingToolkit:Chart x:Name="LineChart"
Title="{Binding Title,RelativeSource={RelativeSource AncestorType=UserControl}}" Margin="10,10,10,0"
Background="LightBlue" >
<chartingToolkit:Chart.Resources>
</chartingToolkit:Chart.Resources>
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="X" />
</chartingToolkit:Chart.Axes>
</chartingToolkit:Chart>
</Grid>
</Grid>
Style MyExpenseBarDataPointStyle = (Style)this.FindResource("MyExpenseBarDataPointStyle");
Style MyBudgetBarDataPointStyle = (Style)this.FindResource("MyBudgetBarDataPointStyle");
BarSeries barSeriesExpense = new BarSeries();
barSeriesExpense.Name = Name.Replace(" ", "");
BarSeries barSeriesBudget = new BarSeries();
barSeriesBudget.Title = "Budget";
barSeriesBudget.Name = Name.Replace(" ", "");
barSeriesExpense.Title = "Dépense";
barSeriesExpense.DataPointStyle = MyExpenseBarDataPointStyle;
barSeriesBudget.DataPointStyle = MyBudgetBarDataPointStyle;
barSeriesExpense.IndependentValueBinding = new Binding("Key"); //date l'axe des X
barSeriesExpense.DependentValueBinding = new Binding("Value"); //money l'axe des Y
barSeriesBudget.IndependentValueBinding = new Binding("Key"); //date l'axe des X
barSeriesBudget.DependentValueBinding = new Binding("Value"); //money l'axe des Y
barSeriesExpense.ItemsSource = dataSource;
barSeriesBudget.ItemsSource = dataSourceMax;
LineChart.Series.Add(barSeriesBudget);
LineChart.Series.Add(barSeriesExpense);

In WPF, building a UserControl with a Button and a Popup, and how to hide Popup when I click MenuItem in it?

I building a UserControl named MenuPopup. And I use this control in project with MVVM.
It like this:
But now, I have no ideal to hide the Popup after click one MenuItem. If hide it by Menuitems' Click events, then how to binding command to ViewModel to handle business logic?
<!--MenuPopup.xaml-->
<UserControl
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:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
mc:Ignorable="d"
x:Class="WpfApplication10.MenuPopup"
x:Name="UserControl">
<UserControl.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Geometry x:Key="ArrowGraph">M 3,6 L 13,6 L 8,12 Z</Geometry>
<Geometry x:Key="LineGraph" >M 12.3,7 L 9,11</Geometry>
<Style x:Key="ArrowMenuButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="#00FFFFFF"/>
<Setter Property="BorderBrush" Value="#FFFFFFFF"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="1"/>
<Path x:Name="ArrowPath" Data="{StaticResource ArrowGraph}" Fill="#FFFFFFFF"/>
<Path x:Name="LinePath" Data="{StaticResource LineGraph}" Fill="#FFD5D5D5" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true"/>
<Trigger Property="ToggleButton.IsChecked" Value="true"/>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#FF219266"/>
<Setter Property="BorderBrush" Value="#FF167559"/>
<Setter Property="Fill" TargetName="LinePath" Value="#FF1E7B57"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" Value="#FF219266"/>
<Setter Property="BorderBrush" Value="#FF7ABEA3"/>
<Setter Property="Fill" TargetName="LinePath" Value="#FF1E7B57"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid>
<Button x:Name="MenuButton" Click="MenuButton_Click" Content="" Width="16" Height="16" BorderThickness="0" Padding="0" Style="{DynamicResource ArrowMenuButtonStyle}" />
<Popup x:Name="MenuButtonPopup" StaysOpen="False" PlacementTarget="{Binding ElementName=MenuButton}" >
<Grid>
<Border Background="White">
<StackPanel >
<MenuItem Header="XX1" />
<MenuItem Header="XX2" />
</StackPanel>
</Border>
</Grid>
</Popup>
</Grid>
</Grid>
</UserControl>
.
// MenuPopup.xaml.cs
namespace WpfApplication10
{
/// <summary>
/// Interaction logic for MenuPopup.xaml
/// </summary>
public partial class MenuPopup : UserControl
{
public MenuPopup()
{
this.InitializeComponent();
}
private void MenuButton_Click(object sender, RoutedEventArgs e)
{
MenuButtonPopup.IsOpen = true;
}
}
}
Update:
Now, I use both click event(which button's) and command. The click event handler in code-behind file, and the command in ViewModel.
<!--parts in MenuPopup.xaml -->
<Grid x:Name="LayoutRoot">
<Button x:Name="MenuButton" Click="MenuButton_Click" Content="" Width="16" Height="16" BorderThickness="0" Padding="0" Style="{DynamicResource ArrowMenuButtonStyle}" />
<Popup x:Name="MenuButtonPopup" StaysOpen="False" PlacementTarget="{Binding ElementName=MenuButton}" >
<Grid>
<Border Background="White">
<StackPanel >
<MenuItem Header="XX1" Click="MenuItem_Click" Command="{Binding IncreaseCommand}"/>
<MenuItem Header="XX2" Click="MenuItem_Click" />
</StackPanel>
</Border>
</Grid>
</Popup>
</Grid>
.
// MenuPopup.xaml.cs
namespace WpfApplication10
{
/// <summary>
/// Interaction logic for MenuPopup.xaml
/// </summary>
public partial class MenuPopup : UserControl
{
public MenuPopup()
{
this.InitializeComponent();
}
private void MenuButton_Click(object sender, RoutedEventArgs e)
{
MenuButtonPopup.IsOpen = true;
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MenuButtonPopup.IsOpen = false;
}
}
}
.
// MainViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
namespace WpfApplication10.ViewModel
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
IncreaseCommand = new RelayCommand(() => ++Cnt);
}
private int cnt = 0;
public int Cnt
{
get { return cnt; }
set { cnt = value; RaisePropertyChanged("Cnt"); }
}
private RelayCommand increaseCommand;
public RelayCommand IncreaseCommand { get; private set; }
}
}
You can have bool property on your viewmodel as IsPopupOpen and bind Popup.IsOpen to this property. Now bind your button Command to the command defined in ViewModel and in your commandhandler set IsPopupOpen to false.
Thanks

Add button to Window Border

I have a WPF window with property WindowStyle="SingleBorderWindow".
Now I want to know how to set a button on left upper corner of the window border.
You probably need to use window chrome library which is described here.
I assume this is so you can re-create the Minimize/Maximize/Close buttons.
You have two options, use a Grid or a DockPanel. I have included a sample for a Grid below.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="2,0" HorizontalAlignment="Right" VerticalAlignment="Top">
</StackPanel>
</Grid>
A Grid with a RowDefinition Height="Auto" that has a StackPanel Orientation="Horizontal" that is right-aligned.
However
If you want to make a true border-less window, you will have more work to do than simply setting the WindowStyle to None.
One main stumbling block I encountered was that when WindowStyle is None, it will not respect the task bar (i.e. overlap it) and you will need to hook into the message pump to set the correct window constraints.
Let me know in the comments if you want to know how to do this, will happy post sample code.
You need to make custom window by setting transparency, background and style like below :
<Window x:Class="WpfApplication2.Window2"
Name="Window2xx"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Title="window1"
xmlns:m="clr-namespace:WpfApplication2"
AllowsTransparency="True" WindowStyle="None"
WindowStartupLocation="CenterOwner" d:DesignWidth="410" StateChanged="Window_StateChanged"
SizeToContent="WidthAndHeight" ShowInTaskbar="False" Background="Transparent">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<m:MasterWindow Width="400">
<m:MasterWindow.WindowTitle>
<ContentPresenter Content="window1" MouseLeftButtonDown="Window_MouseLeftButtonDown"></ContentPresenter>
</m:MasterWindow.WindowTitle>
<m:MasterWindow.Content>
<Grid>
</Grid>
</m:MasterWindow.Content>
</m:MasterWindow>
</Grid>
</Window>
Code behind window2 :
namespace WpfApplication2
{
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void Window_StateChanged(object sender, EventArgs e)
{
if (((Window)sender).WindowState == WindowState.Maximized)
((Window)sender).WindowState = WindowState.Normal;
}
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
try
{
DragMove();
}
catch ()
{}
}
}
}
Master window is like below :
namespace WpfApplication2
{
public class MasterWindow : ContentControl
{
public static RoutedCommand CloseWindowCommand;
static MasterWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MasterWindow), new FrameworkPropertyMetadata(typeof(MasterWindow)));
CloseWindowCommand = new RoutedCommand("CloseWindow", typeof(MasterWindow));
CommandManager.RegisterClassCommandBinding(typeof(MasterWindow), new CommandBinding(CloseWindowCommand, CloseWindowEvent));
}
public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register("WindowTitle", typeof(object), typeof(MasterWindow), new UIPropertyMetadata());
public object WindowTitle
{
get { return (object)GetValue(WindowTitleProperty); }
set { SetValue(WindowTitleProperty, value); }
}
private static void CloseWindowEvent(object sender, ExecutedRoutedEventArgs e)
{
MasterWindow control = sender as MasterWindow;
if (control != null)
{
Window objWindow = Window.GetWindow(((FrameworkElement)sender));
if (objWindow != null)
{
if (objWindow.Name.ToLower() != "unlockscreenwindow")
{
Window.GetWindow(((FrameworkElement)sender)).Close();
}
}
}
}
}
}
Styles for master window :
<ResourceDictionary
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"
mc:Ignorable="d"
xmlns:local="clr-namespace:WpfApplication2"
x:Class="MasterWindow">
<Style x:Key="WindowTitle" TargetType="ContentPresenter">
<Setter Property="Control.FontFamily" Value="Segoe UI"></Setter>
<Setter Property="Control.FontSize" Value="14"></Setter>
<Setter Property="Control.FontWeight" Value="SemiBold"></Setter>
<Setter Property="Control.Foreground" Value="White"></Setter>
<Setter Property="Control.VerticalAlignment" Value="Top"></Setter>
<Setter Property="Control.HorizontalAlignment" Value="Left"></Setter>
<Setter Property="Control.VerticalContentAlignment" Value="Top"></Setter>
</Style>
<Style x:Key="closebutton" BasedOn="{x:Null}" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle
Opacity="1"
RadiusX="2"
RadiusY="2"
Stroke="#ffffff"
StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush
StartPoint="0.6190476190476191,-0.5"
EndPoint="1.1128888811383928,1.426776123046875">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop
Color="#2E4C87"
Offset="0" />
<GradientStop
Color="#FFffffff"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Path
Margin="5,5,5,5"
Stretch="Fill"
Opacity="1"
Data="M 808.8311767578125,278.7662353515625 C808.8311767578125,278.7662353515625 820,268 820,268 "
Stroke="#ffffff"
StrokeThickness="2" />
<Path
Margin="5,5,5,5"
Stretch="Fill"
Opacity="1"
Data="M 809.4155883789062,268.3636474609375 C809.4155883789062,268.3636474609375 820,279 820,279 "
Stroke="#ffffff"
StrokeThickness="2" />
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:MasterWindow}">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MasterWindow}">
<StackPanel>
<Border x:Name="border" Background="WhiteSmoke" BorderBrush="#2E4C87" BorderThickness="7" CornerRadius="8,8,8,8" >
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" Opacity="0.75" ShadowDepth="8"></DropShadowBitmapEffect>
</Border.BitmapEffect>
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.95" ScaleY="0.95"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Border.RenderTransform>
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" From="0" To="0.96" Duration="0:0:0.6"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" From="0" To="0.96" Duration="0:0:0.6"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Grid HorizontalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="32"></RowDefinition>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border BorderThickness="5,5,3,0" Background="#2E4C87" BorderBrush="#2E4C87" CornerRadius="5,4,0,0" VerticalAlignment="Top" Height="32" Margin="-6,-6,-4,0" >
<Grid Background="Transparent" HorizontalAlignment="Stretch" Height="32" VerticalAlignment="Center" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding WindowTitle}" Margin="0,4,0,0" HorizontalAlignment="Stretch" Style="{StaticResource WindowTitle}" />
<Button Name="btnClose" Style="{StaticResource closebutton}" Cursor="Hand" Command="{x:Static local:MasterWindow.CloseWindowCommand}" VerticalAlignment="Top" Height="18" HorizontalAlignment="Right" Width="18" Margin="0,5,8,0" Grid.Column="1" />
</Grid>
</Border>
<Border BorderBrush="Transparent" BorderThickness="7,0,7,7" VerticalAlignment="Top" HorizontalAlignment="Left" CornerRadius="0,0,10,10" Grid.Row="1"></Border>
<ContentPresenter Grid.Row="1" Content="{TemplateBinding Content}" VerticalAlignment="Top" Margin="0,-6,0,0"/>
</Grid>
</Border>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Categories