Custom Button WPF don't bind property - c#

I did a custom button in WPF and I added some properties to use to in style. But some stuff doesn't work correctly
Control.
public class CustomButton : Button
{
public static readonly DependencyProperty TextProperty;
public static readonly DependencyProperty ImageProperty;
public static readonly DependencyProperty ImageRollvoerProperty;
public static readonly DependencyProperty TextMarginProperty;
static CustomButton()
{
TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(CustomButton), new UIPropertyMetadata(null));
ImageProperty = DependencyProperty.Register("Image", typeof(ImageSource), typeof(CustomButton), new UIPropertyMetadata(null));
ImageProperty = DependencyProperty.Register("ImageRollvoer", typeof(ImageSource), typeof(CustomButton), new UIPropertyMetadata(null));
TextMarginProperty = DependencyProperty.Register("TextMargin", typeof(string), typeof(CustomButton), new UIPropertyMetadata(null));
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
public ImageSource ImageImageRollvoer
{
get { return (ImageSource)GetValue(ImageRollvoerProperty); }
set { SetValue(ImageRollvoerProperty, value); }
}
public string TextMargin
{
get { return (string)GetValue(TextMarginProperty); }
set { SetValue(TextMarginProperty, value); }
}
}
Style
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:XposButton}">
<Grid ClipToBounds="True">
<Grid.RowDefinitions>
<RowDefinition Height="{TemplateBinding Height}" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{TemplateBinding Width}" />
</Grid.ColumnDefinitions>
<local:ClippingBorder Grid.Row="0" Grid.Column="0" BorderThickness="0" CornerRadius="10" Background="{StaticResource OxxoMetroBackground}" BorderBrush="{StaticResource OxxoMetroBorder}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<local:ClippingBorder Background="{StaticResource OxxoMetroBackground}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="2" CornerRadius="9">
<local:ClippingBorder x:Name="Overlay" ClipToBounds="True" Background="Transparent" BorderBrush="{StaticResource OxxoMetroBorder}" BorderThickness="0">
<Image Name="btnImage" Source="{TemplateBinding Image}" Style="{StaticResource ImageUninhabitable}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</local:ClippingBorder>
</local:ClippingBorder>
</local:ClippingBorder>
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" Margin="{TemplateBinding TextMargin}" Text="{TemplateBinding Text}" Style="{DynamicResource TextBlockMenuImg}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
View
<ctrl:CustomButton FontFamily="Roboto" Margin="17" TextMargin="0,20,0,0" Width="150" Image="{Binding Path=ImageUrl}" Text="{Binding ShowName}" x:Name="btnMenu" Style="{StaticResource CustomButtonStyle}" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path= DataContext.SelectMenuCommand}" CommandParameter="{Binding}" />
The Image, and text are correctly displayed, the FontFamily, and TextMargin doesn't work correctly.

The binding on Margin probably isn't working because the property should be defined as a Thickness type rather than String.
public Thickness TextMargin

Related

Multiple ItemsPresenters in a WPF

I'm doing something similar to Multiple Content Presenters in a WPF User control.
I'm creating a visual widget for a conditional if statement, and I want there to be both true and false content. Where it differs from the original post is that I want to be able to have multiple items in the true and false content. Whereas I can bind ContentPresenter's Content property, ItemsPresenter has no similar thing to bind to.
Is there a way around this that I can build into the control (not just have the calling XAML wrap it in a Grid/StackPanel/etc.)?
public class ConditionalBlock : Control
{
static ConditionalBlock ()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ConditionalBlock), new FrameworkPropertyMetadata(typeof(ConditionalBlock)));
}
public ConditionalBlock ()
{
Background = new SolidColorBrush(Color.FromRgb(0x45, 0x0F, 0x45));
}
public static readonly DependencyProperty LeftWidthProperty = DependencyProperty.Register("LeftWidth", typeof(double), typeof(ConditionalBlock), new UIPropertyMetadata(20.0));
public double LeftWidth
{
get => (double) GetValue(LeftWidthProperty);
set => SetValue(LeftWidthProperty, value);
}
public static readonly DependencyProperty BottomHeightProperty = DependencyProperty.Register("BottomHeight", typeof(double), typeof(ConditionalBlock), new UIPropertyMetadata(10.0));
public double BottomHeight
{
get => (double) GetValue(BottomHeightProperty);
set => SetValue(BottomHeightProperty, value);
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(ConditionalBlock), new UIPropertyMetadata("If"));
public string Title
{
get => (string) GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
public static readonly DependencyProperty HasSettingsProperty = DependencyProperty.Register("HasSettings", typeof(bool), typeof(ConditionalBlock), new UIPropertyMetadata(true));
public bool HasSettings
{
get => (bool) GetValue(HasSettingsProperty);
set => SetValue(HasSettingsProperty, value);
}
public static readonly DependencyProperty TrueTitleProperty = DependencyProperty.Register("TrueTitle", typeof(string), typeof(ConditionalBlock), new UIPropertyMetadata("True"));
public string TrueTitle
{
get => (string) GetValue(TrueTitleProperty);
set => SetValue(TrueTitleProperty, value);
}
public static readonly DependencyProperty TrueContentProperty = DependencyProperty.Register("TrueContent", typeof(object), typeof(ConditionalBlock), null);
public object TrueContent
{
get => GetValue(TrueContentProperty);
set => SetValue(TrueContentProperty, value);
}
public static readonly DependencyPropertyKey HasTrueItemsProperty = DependencyProperty.RegisterReadOnly("HasTrueItems", typeof(bool), typeof(ConditionalBlock), new UIPropertyMetadata(false));
public bool HasTrueItmes => TrueContent != null;
public static readonly DependencyProperty ElseHeightProperty = DependencyProperty.Register("ElseHeight", typeof(double), typeof(ConditionalBlock), new UIPropertyMetadata(10.0));
public double ElseHeight
{
get => (double) GetValue(ElseHeightProperty);
set => SetValue(ElseHeightProperty, value);
}
public static readonly DependencyProperty FalseTitleProperty = DependencyProperty.Register("FalseTitle", typeof(string), typeof(ConditionalBlock), new UIPropertyMetadata("False"));
public string FalseTitle
{
get => (string) GetValue(FalseTitleProperty);
set => SetValue(FalseTitleProperty, value);
}
public static readonly DependencyProperty FalseContentProperty = DependencyProperty.Register("FalseContent", typeof(object), typeof(ConditionalBlock), null);
public object FalseContent
{
get => GetValue(FalseContentProperty);
set => SetValue(FalseContentProperty, value);
}
public static readonly DependencyPropertyKey HasFalseItemsProperty = DependencyProperty.RegisterReadOnly("HasFalseItems", typeof(bool), typeof(ConditionalBlock), new UIPropertyMetadata(false));
public bool HasFalseItmes => FalseContent != null;
}
<Style TargetType="{x:Type local:ConditionalBlock}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ConditionalBlock}">
<Grid Background="White"
Margin="0,1">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--This is the top bar-->
<Border Grid.Row="0"
Grid.ColumnSpan="3"
CornerRadius="4"
Background="{TemplateBinding Background}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="7,0,0,0"
VerticalAlignment="Center"
Text="{TemplateBinding Title}"
Foreground="White" />
<Image
Grid.Column="1"
Source="{StaticResource SettingsIcon}"
Visibility="{TemplateBinding HasSettings, Converter={StaticResource BooleanVisibilityConverter}}"
VerticalAlignment="Center"
MaxWidth="10"
Margin="0,1,5,0"
Stretch="Uniform" />
</Grid>
</Border>
<!--This is the true block-->
<Grid
Grid.Row="1"
Grid.Column="0"
Width="{TemplateBinding LeftWidth}"
Visibility="{TemplateBinding HasTrueItems, Converter={StaticResource BooleanVisibilityConverter}}"
Margin="0,-3.5"
Background="{TemplateBinding Background}">
<TextBlock
VerticalAlignment="Center"
Text="{TemplateBinding TrueTitle}"
Foreground="White">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>
</TextBlock>
</Grid>
<Grid
Grid.Row="1"
Grid.Column="1"
Visibility="{TemplateBinding HasTrueItems, Converter={StaticResource BooleanVisibilityConverter}}"
Margin="-1"
Background="{TemplateBinding Background}">
<Border Margin="1,1,-1,1"
CornerRadius="2,0,0,2"
Background="White" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="2"
Visibility="{TemplateBinding HasTrueItems, Converter={StaticResource BooleanVisibilityConverter}}"
Margin="0,0,0,1">
<ContentPresenter Content="{TemplateBinding TrueContent}" />
</Grid>
<!--This is the else bar-->
<Border Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="3"
Height="{TemplateBinding ElseHeight}"
CornerRadius="4"
Background="{TemplateBinding Background}" />
<!--This is the false block-->
<Grid
Grid.Row="3"
Grid.Column="0"
Width="{TemplateBinding LeftWidth}"
Visibility="{TemplateBinding HasFalseItems, Converter={StaticResource BooleanVisibilityConverter}}"
Margin="0,-3.5"
Background="{TemplateBinding Background}">
<TextBlock VerticalAlignment="Center"
Text="{TemplateBinding FalseTitle}"
Foreground="White">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>
</TextBlock>
</Grid>
<Grid
Grid.Row="3"
Grid.Column="1"
Visibility="{TemplateBinding HasFalseItems, Converter={StaticResource BooleanVisibilityConverter}}"
Margin="-1"
Background="{TemplateBinding Background}">
<Border Margin="1,1,-1,1"
CornerRadius="2,0,0,2"
Background="White" />
</Grid>
<Grid
Grid.Row="3"
Grid.Column="2"
Visibility="{TemplateBinding HasFalseItems, Converter={StaticResource BooleanVisibilityConverter}}"
Margin="0,0,0,1">
<ContentPresenter Content="{TemplateBinding FalseContent}" />
</Grid>
<!--This is the bottom bar-->
<Border Grid.Row="4"
Grid.Column="0"
Grid.ColumnSpan="3"
Height="{TemplateBinding BottomHeight}"
CornerRadius="4"
Background="{TemplateBinding Background}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF Custom SplitView Control

I just wanted to start off saying I've seen similar posts with the same issue but they give a solution not suitable to my scenario. I'm making a SplitView Control as shown below. Problem is the Control has 3 areas where users can place whatever controls they want, but those controls can't be named via this error:
Cannot set Name attribute value 'Item1' on element 'ListViewItem'. 'ListViewItem' is under the scope of element 'SplitView', which already had a name registered when it was defined in another scope.
How can I fix this? I don't want the implementation of this control to have to always have to add some code to get around this error. Could I add a 3 template areas in this control so the user can make a their own template with content they want inside each area. How would I do this? I'm open to other ideas.
Markup
<UserControl x:Name="ThisControl" x:Class="ns.SplitView"
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:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Margin="10" Grid.Row="0" Grid.Column="0" x:Name="OpenPaneButton" Width="50" Height="50" Click="OpenPaneButton_Click" Background="{x:Null}" BorderBrush="{x:Null}" Focusable="False" >
<Viewbox>
<Canvas Width="300" Height="210">
<Path StrokeThickness="1" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="{Binding HamburgerButtonColor, ElementName=ThisControl}" Fill="{Binding HamburgerButtonColor, ElementName=ThisControl}">
<Path.Data>
<RectangleGeometry Rect="0,0,300,50" RadiusX="25" RadiusY="25" />
</Path.Data>
</Path>
<Path StrokeThickness="1" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="{Binding HamburgerButtonColor, ElementName=ThisControl}" Fill="{Binding HamburgerButtonColor, ElementName=ThisControl}">
<Path.Data>
<RectangleGeometry Rect="0,80,300,50" RadiusX="25" RadiusY="25" />
</Path.Data>
</Path>
<Path StrokeThickness="1" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="{Binding HamburgerButtonColor, ElementName=ThisControl}" Fill="{Binding HamburgerButtonColor, ElementName=ThisControl}">
<Path.Data>
<RectangleGeometry Rect="0,160,300,50" RadiusX="25" RadiusY="25" />
</Path.Data>
</Path>
</Canvas>
</Viewbox>
</Button>
<ContentPresenter x:Name="MainTitleContent" Panel.ZIndex="1" Content="{Binding TitleContent, ElementName=ThisControl}" Grid.Row="0" Grid.Column="1" Focusable="True"/>
<ContentPresenter x:Name="Pane" Panel.ZIndex="1" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="0" HorizontalAlignment="Left" Content="{Binding PaneContent, ElementName=ThisControl}" LostFocus="Pane_LostFocus" LostMouseCapture="Pane_LostMouseCapture" LostKeyboardFocus="Pane_LostKeyboardFocus" LostTouchCapture="Pane_LostTouchCapture" LostStylusCapture="Pane_LostStylusCapture" Focusable="True"/>
<ContentPresenter x:Name="Content" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="1" Content="{Binding MainContent, ElementName=ThisControl}" Focusable="True"/>
</Grid>
</UserControl>
Code Behind
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace ns
{
public partial class SplitView
{
/// <summary>
/// A simple state to know if the pane is open
/// </summary>
public bool PaneIsOpen
{
get { return (bool)GetValue(PaneIsOpenProperty); }
set { SetValue(PaneIsOpenProperty, value); }
}
public static readonly DependencyProperty PaneIsOpenProperty = DependencyProperty.Register("PaneIsOpen", typeof(bool), typeof(SplitView));
public SolidColorBrush HamburgerButtonColor
{
get { return (SolidColorBrush)GetValue(HamburgerButtonColorProperty); }
set { SetValue(HamburgerButtonColorProperty, value); }
}
public static readonly DependencyProperty HamburgerButtonColorProperty = DependencyProperty.Register("HamburgerButtonColor", typeof(SolidColorBrush), typeof(SplitView), new UIPropertyMetadata(new SolidColorBrush(Colors.Black)));
public double PaneWidth
{
get { return (double)GetValue(PaneWidthProperty); }
set { SetValue(PaneWidthProperty, value); }
}
public static readonly DependencyProperty PaneWidthProperty = DependencyProperty.Register("PaneWidth", typeof(double), typeof(SplitView), new PropertyMetadata(null));
public object MainContent
{
get { return GetValue(MainContentProperty); }
set { SetValue(MainContentProperty, value); }
}
public static readonly DependencyProperty MainContentProperty = DependencyProperty.Register("MainContent", typeof(object), typeof(SplitView), new PropertyMetadata(null));
public object PaneContent
{
get { return GetValue(PaneContentProperty); }
set { SetValue(PaneContentProperty, value); }
}
public static readonly DependencyProperty PaneContentProperty = DependencyProperty.Register("PaneContent", typeof(object), typeof(SplitView), new PropertyMetadata(null));
public object TitleContent
{
get { return GetValue(TitleContentProperty); }
set { SetValue(TitleContentProperty, value); }
}
public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register("TitleContent", typeof(object), typeof(SplitView), new PropertyMetadata(null));
private readonly Duration PaneAnimationDuration = new Duration(new TimeSpan());
private DoubleAnimation ClosePaneAnimation => new DoubleAnimation {Duration = PaneAnimationDuration, To = 0, From = PaneWidth };
private DoubleAnimation OpenPaneAnimation => new DoubleAnimation {Duration = PaneAnimationDuration, To = PaneWidth, From = 0 };
public SplitView()
{
InitializeComponent();
}
private void OpenPaneButton_Click(object sender, RoutedEventArgs e)
{
PaneIsOpen = !PaneIsOpen;
//Debug.WriteLine($"pane is open: {PaneIsOpen}");
if (PaneIsOpen)
{
Pane.BeginAnimation(WidthProperty, OpenPaneAnimation);
Pane.Focus();
}
else
{
Pane.BeginAnimation(WidthProperty, ClosePaneAnimation);
}
}
private void Pane_LostFocus(object sender, RoutedEventArgs e)
{
PaneLostFocus();
e.Handled = true;
}
private void Pane_LostMouseCapture(object sender, MouseEventArgs e)
{
PaneLostFocus();
e.Handled = true;
}
private void PaneLostFocus()
{
if (PaneIsOpen)
{
PaneIsOpen = false;
Pane.BeginAnimation(WidthProperty, ClosePaneAnimation);
}
}
private void Pane_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
PaneLostFocus();
e.Handled = true;
}
private void Pane_LostTouchCapture(object sender, TouchEventArgs e)
{
PaneLostFocus();
e.Handled = true;
}
private void Pane_LostStylusCapture(object sender, StylusEventArgs e)
{
PaneLostFocus();
e.Handled = true;
}
}
}
Implementation
<customControls:SplitView x:Name="SplitView" PaneWidth="250" HamburgerButtonColor="{StaticResource AccentColorBrush2}">
<customControls:SplitView.MainContent>
<Grid>
</Grid>
</customControls:SplitView.MainContent>
<customControls:SplitView.PaneContent>
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Navigation" Style="{StaticResource Header1}" Margin="10,5,5,5"/>
<!-- I can't name controls in these content areas -->
<ListView Grid.Row="1" BorderThickness="0" SelectionChanged="PaneItemsListView_SelectionChanged">
<ListViewItem x:Name="Item1" Style="{StaticResource SplitViewItemsStyle}" ">
<TextBlock Text="Project Explorer" Margin="20,5,10,5"/>
</ListViewItem>
<ListViewItem Style="{StaticResource SplitViewItemsStyle}" Tag="FieldServicesItem">
<TextBlock Text="Field Services" Margin="20,5,10,5"/>
</ListViewItem>
<ListViewItem Style="{StaticResource SplitViewItemsStyle}" Tag="ReportManagerItem">
<TextBlock Text="Report Manager" Margin="20,5,10,5"/>
</ListViewItem>
</ListView>
</Grid>
</customControls:SplitView.PaneContent>
<customControls:SplitView.TitleContent>
<Grid>
<TextBlock HorizontalAlignment="Center" Text="Current View" VerticalAlignment="Center" Style="{StaticResource Header1}"/>
</Grid>
</customControls:SplitView.TitleContent>
</customControls:SplitView>

Can't create dependency property in a UserControl in a Windows Runtime Component library

I wanted to created data bindable property inside a user control. And this user control contains inside a "Windows Runtime Component" project. I used below code to create property.
public MyItem CurrentItem
{
get { return (MyItem)GetValue(CurrentItemProperty); }
set { SetValue(CurrentItemProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentItem.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentItemProperty =
DependencyProperty.Register("CurrentItem", typeof(MyItem), typeof(CollapseUserControl), new PropertyMetadata(null));
When I compile the project I get below error.
Type 'HierachyLib.CollapseUserControl' contains externally visible field 'HierachyLib.CollapseUserControl.CurrentItemProperty'. Fields can be exposed only by structures.
Update 1 - Source code for whole class
public sealed partial class CollapseUserControl : UserControl, IHierarchyHeightFix
{
public MyItem CurrentItem
{
get { return (MyItem)GetValue(CurrentItemProperty); }
set { SetValue(CurrentItemProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentItem. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentItemProperty =
DependencyProperty.Register("CurrentItem", typeof(MyItem), typeof(CollapseUserControl), new PropertyMetadata(null));
Boolean viewState = true;
public CollapseUserControl()
{
this.DataContext = CurrentItem;
this.InitializeComponent();
this.Loaded += CollapseUserControl_Loaded;
}
void CollapseUserControl_Loaded(object sender, RoutedEventArgs e)
{
LoadData();
if (this.Height.Equals(double.NaN))
{
this.Height = 50;
}
//this.Height = 50;
//this.Width = double.NaN;
}
private void LoadData()
{
if (CurrentItem != null)
{
if (CurrentItem.IsValueControl)
{
ChildItemContainer.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
ValueItem.Visibility = Windows.UI.Xaml.Visibility.Visible;
ValueItem.Text = CurrentItem.Value;
}
else
{
ChildItemContainer.Visibility = Windows.UI.Xaml.Visibility.Visible;
ValueItem.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
ChildItems.ItemsSource = CurrentItem.Childs;
//foreach (MyItem item in CurrentItem.Childs)
//{
// CollapseUserControl control = new CollapseUserControl();
// control.CurrentItem = item;
// ChildItems.Items.Add(control);
//}
ChildItems.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (viewState)
{
ChildItems.Visibility = Windows.UI.Xaml.Visibility.Visible;
//show.Begin();
}
else
{
//hide.Begin();
ChildItems.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
viewState = !viewState;
}
private void hide_Completed_1(object sender, object e)
{
ChildItems.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
private void show_Completed_1(object sender, object e)
{
}
}
Update 2 : XAML Code
<UserControl
x:Class="HierachyLib.CollapseUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HierachyLib"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<UserControl.Resources>
<DataTemplate x:Key="ReviewsItemsTemplate">
<StackPanel Margin="0,0,0,20">
<TextBlock Text="TEST" />
<TextBlock Text="TEST"/>
</StackPanel>
</DataTemplate>
<ItemsPanelTemplate x:Key="ReviewsItemsPanelTemplate">
<StackPanel Margin="0,0,0,0" Width="Auto"/>
</ItemsPanelTemplate>
</UserControl.Resources>
<!--xmlns:my="clr-namespace:HierarchyCollapse"-->
<Grid>
<Grid Name="ChildItemContainer">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Margin="0,0,70,0" Fill="Transparent" Canvas.ZIndex="4"/>
<ListView HorizontalContentAlignment="Stretch" Background="#FF6599CD" CanDragItems="False" CanReorderItems="False" Grid.Row="0"
ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollMode="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Disabled">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Height="40">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<TextBlock Text="Sample Text" FontSize="17" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0" Canvas.ZIndex="10"/>
<Image PointerPressed="Button_Click_1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Source="Assets/arrw_right.png" Stretch="None" Margin="0,0,10,0"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListViewItem />
</ListView>
<ListView Grid.Row="1"
IsHitTestVisible="True"
CanDragItems="True"
CanReorderItems="True"
AllowDrop="True"
Name="ChildItems"
SelectionMode="None"
IsItemClickEnabled="False">
<ListView.ItemTemplate>
<DataTemplate>
<local:CollapseUserControl CurrentItem="{Binding RelativeSource={RelativeSource Self}}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
<TextBlock Name="ValueItem" Margin="0,0,0,0" Height="40" FontSize="36"></TextBlock>
</Grid>
New error I get:
Failed to create a 'Windows.UI.Xaml.PropertyPath' from the text ''.
Error comes from <local:CollapseUserControl CurrentItem="{Binding RelativeSource={RelativeSource Self}}" />.
It seems like you can mark your property as internal and then it starts working...
internal static readonly DependencyProperty CurrentItemProperty...
EDIT*
A better approach that seems to be what the platform controls do is to have an actual CLR property that exposes the DependencyProperty object - something like this:
private static readonly DependencyProperty CurrentItemPropertyField =
DependencyProperty.Register/RegisterAttached(...);
internal static DependencyProperty CurrentItemProperty
{
get
{
return CurrentItemPropertyField;
}
}
This allows tools such as Blend to discover the properties.
You can use an automatic property setting the default value (from c# 5) like this:
public static DependencyProperty CurrentItemPropertyField { get; } =
DependencyProperty.Register("Value", typeof(string), typeof(MyControl), new PropertyMetadata("{No Value}"));
Works also for UWP applications

WPF CustomControl ControlTemplate update TemplateBinding at Runtime

I have been experimenting with WPF and using a CustomControl have made my own panel type so I can make all my panels look like a box with backgrounds, rounded corners etc.
The trouble I am not having is I want to change the property of an item at runtime that is bound using TemplateBinding.
My issue is changing this through code is not working.
Was hoping someone could spot my error and tell me where I am being slightly dense.
This finds the contentControl and changes the value, this just never appears in the application, as if the binding is not active.
Hope someone can help.
The control Template.
<ControlTemplate x:Key="ContentBoxControlTemplate" TargetType="{x:Type local:ContentBox}"><Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.124*"/>
<RowDefinition Height="0.876*"/>
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="0" HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" CornerRadius="20" Grid.RowSpan="2" Style="{TemplateBinding Style}" />
<Rectangle HorizontalAlignment="Stretch" Height="Auto" RadiusY="0" StrokeThickness="0" VerticalAlignment="Stretch" Width="Auto" Margin="10,0,10,20" Fill="White" Grid.Row="1"/>
<Rectangle Fill="{DynamicResource TopInnerShadow}" HorizontalAlignment="Stretch" Height="Auto" RadiusY="0" StrokeThickness="0" VerticalAlignment="Stretch" Width="Auto" Margin="10,0,10,20" Grid.Row="1"/>
<Rectangle Fill="{DynamicResource RightInnerShadow}" HorizontalAlignment="Stretch" Height="Auto" RadiusY="0" StrokeThickness="0" VerticalAlignment="Stretch" Width="Auto" Margin="10,0,10,20" Grid.Row="1"/>
<TextBlock Grid.Row="0" x:Name="txtBoxHeading" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" VerticalAlignment="Stretch" d:LayoutOverrides="Width, Height" Foreground="White" FontSize="36" FontFamily="Arial" Margin="20,5"/>
<Grid Grid.Row="1">
<ContentControl Content="{TemplateBinding Content}" Margin="10,0,10,20"/>
</Grid>
</Grid>
</ControlTemplate>
The ContentControl
public class ContentBox : ContentControl
{
static ContentBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ContentBox), new FrameworkPropertyMetadata(typeof(ContentBox)));
}
private string _title = "";
public string Title
{
get { return _title; }
set { _title = value; }
}
// Dependency Property
public static DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(ContentBox), new FrameworkPropertyMetadata("Title"));
}
The xaml for using the content control
And finally the code to change the property
(this.Parent as ContentBox).Title = "Campaign: " + campaigns[0].Name;
I found my mistake, and I was as I thought, being silly!!
In the ContentControl I was not setting the dependancy property properly.
Changing the property in the contentcontrol to the following fixed my problem
public string Title
{
get { return (string)this.GetValue(TitleProperty); }
set { this.SetValue(TitleProperty, value); }
}

How Do I Set Multiple Content Dynamically in a Button in WPF

I created the following xaml:
<Button x:Name="PriceButton">
<Button.Template>
<ControlTemplate>
<Border x:Name="ButtonBorder"
CornerRadius="2"
Background="{StaticResource DarkReflectionBrush}"
BorderBrush="Black"
BorderThickness="1" HorizontalAlignment="Stretch">
<ContentPresenter
VerticalAlignment="Center"
HorizontalAlignment="Left">
<ContentPresenter.Content>
<Grid x:Name="ContentGrid" HorizontalAlignment="Left" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="15*" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="Price" Grid.Column="0" FontFamily="Calibri" FontSize="8"
VerticalAlignment="Bottom" Text="{Binding Path=PriceText}"
Foreground="{Binding Path=PriceColor}" ></TextBlock>
<TextBlock x:Name="Main" Grid.Column="1" FontFamily="Calibri" FontSize="14"
Text="{Binding Path=MainText}"
Foreground="{Binding Path=MainTextColor}" />
<TextBlock x:Name="Vol" Grid.Column="2" FontFamily="Calibri" FontSize="8"
VerticalAlignment="Bottom" Text="{Binding Path=VolatilityText}"
Foreground="{Binding Path=VolatilityColor}" />
</Grid>
</ContentPresenter.Content>
</ContentPresenter>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsPressed" Value="true">
<Setter TargetName="ButtonBorder" Property="Background" Value="{StaticResource PressedBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
Here's the Code Behind:
public static readonly DependencyProperty PriceTextProperty =
DependencyProperty.Register(
"PriceText",
typeof (string),
typeof (LivePriceVolButton),
new FrameworkPropertyMetadata(string.Empty, OnPriceTextChanged));
public string PriceText {
get {
return (string)GetValue(PriceTextProperty);
}
set {
SetValue(PriceTextProperty, value);
}
}
public static readonly DependencyProperty PriceColorProperty =
DependencyProperty.Register(
"PriceColor",
typeof (Color),
typeof (LivePriceVolButton),
new FrameworkPropertyMetadata(Colors.White));
public Color PriceColor {
get {
return (Color) GetValue(PriceColorProperty);
}
set {
SetValue(PriceColorProperty, value);
}
}
public static readonly DependencyProperty MainTextProperty =
DependencyProperty.Register(
"MainText",
typeof (string),
typeof (LivePriceVolButton),
new FrameworkPropertyMetadata(string.Empty));
public string MainText {
get {
return (string) GetValue(MainTextProperty);
}
set {
SetValue(MainTextProperty, value);
}
}
public static readonly DependencyProperty MainTextColorProperty =
DependencyProperty.Register(
"MainTextColor",
typeof(Color),
typeof(LivePriceVolButton),
new FrameworkPropertyMetadata(Colors.White));
public Color MainTextColor {
get {
return (Color) GetValue(MainTextColorProperty);
}
set {
SetValue(MainTextColorProperty, value);
}
}
public static readonly DependencyProperty VolatilityTextProperty =
DependencyProperty.Register(
"VolatilityText",
typeof(string),
typeof(LivePriceVolButton),
new FrameworkPropertyMetadata(string.Empty));
public string VolatilityText {
get {
return (string) GetValue(VolatilityTextProperty);
}
set {
SetValue(VolatilityTextProperty, value);
}
}
public static readonly DependencyProperty VolatilityColorProperty =
DependencyProperty.Register(
"VolatilityColor",
typeof(Color),
typeof(LivePriceVolButton),
new FrameworkPropertyMetadata(Colors.White));
public Color VolatilityColor {
get {
return (Color) GetValue(VolatilityColorProperty);
}
set {
SetValue(VolatilityColorProperty, value);
}
}
When I insert my user control onto a form like this
<my:LivePriceVolButton Margin="43.03,0,0,32" x:Name="livePriceVolButton1"
xmlns:my="clr-namespace:MultiTextBlockButton" HorizontalAlignment="Left"
Width="91.703" Height="30" VerticalAlignment="Bottom"
MainText="MID" MainTextColor="LightBlue" PriceColor="Red" PriceText="1234.56"
VolatilityText="12.2%" VolatilityColor="Aqua" />
I don't see anything in the button at all. Any ideas?
Thanks
You have to set the DataContext for the Button to be equal to the parent UserControl for your Bindings to work. Try something like this:
<UserControl x:Name="uc" ...>
<Button x:Name="PriceButton" DataContext="{Binding ElementName=uc}">
<!--Other code here...-->
</Button>
</UserControl>
I also see that you're using "Color" as the Type for some of your DependencyProperties. I suggest you change them to "Brush" instead. Otherwise the related bindings (e.g. Foreground="{Binding VolatilityColor}") won't work.

Categories

Resources