Get attached property value from content in contentpresenter - c#

I've made a custom window that has a template defined in a resource dictionary. The window has no title bar.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dsControls="clr-namespace:Something">
<Style x:Key="WindowRegionStyle"
TargetType="Window">
/** Other setters **/
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Border Background="{StaticResource WindowBackground}"
BorderBrush="{StaticResource BorderBrushColor}"
BorderThickness="1"
CornerRadius="8"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border CornerRadius="8,8,0,0"
BorderBrush="{StaticResource BorderBrushColor}"
Background="{StaticResource HeaderColor}"
Grid.ColumnSpan="2"
Grid.Row="0">
<Label Content="{Binding Path=(dsControls:WindowDetails.Title), RelativeSource={RelativeSource TemplatedParent}}"
FontSize="20" />
</Border>
<ContentPresenter Grid.Row="1" Grid.ColumnSpan="2" Content="{TemplateBinding Content}" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The content that is added to this template is a UserControl. That all works.
But now I want to define a title in the UserControl. To set the title, I made an attached property 'WindowDetails.Title'.
public static class WindowDetails
{
public static string GetTitle(DependencyObject obj)
{
return (string)obj.GetValue(TitleProperty);
}
public static void SetTitle(DependencyObject obj, string value)
{
obj.SetValue(TitleProperty, value);
}
// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleProperty =
DependencyProperty.RegisterAttached("Title", typeof(string), typeof(WindowDetails), new PropertyMetadata(""));
}
And I set the the title in the UserControl like this:
<UserControl x:Class="Something.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dsControls="clr-namespace:Something"
Width="400"
dsControls:WindowDetails.Title="Test">
/** Some content **/
</UserControl>
The problem
I cannot bind the property value to the label in my template.
What I already tried (and went wrong)
<Label Content="{Binding Path=(dsControls:WindowDetails.Title), RelativeSource={RelativeSource TemplatedParent}}"
FontSize="20" />
and
<Label Content="{Binding Path=(dsControls:WindowDetails.Title), RelativeSource={RelativeSource Self}}"
FontSize="20" />
Also, changing the OwnerType of the Attached property:
To WindowDetails
public static readonly DependencyProperty TitleProperty =
DependencyProperty.RegisterAttached("Title", typeof(string), typeof(WindowDetails), new PropertyMetadata(""));
When I do this, the property is not set. But the content of the label has the default property value.
To UserControl
public static readonly DependencyProperty TitleProperty =
DependencyProperty.RegisterAttached("Title", typeof(string), typeof(UserControl), new PropertyMetadata(""));
When I do this, the property is set, but the content of the label has no value.
Question
How can I set the attached property in my UserControl and bind it to the content of the label in my template?
Thanks in advance!
Greetings
Loetn

This is how you can do this: Give x:Name to your ContentPresenter and refer to it in binding the label.
<Border CornerRadius="8,8,0,0"
BorderBrush="{StaticResource BorderBrushColor}"
Background="{StaticResource HeaderColor}"
Grid.ColumnSpan="2"
Grid.Row="0">
<Label Content="{Binding Path=Content.(dsControls:WindowDetails.Title), ElementName="myPresenter"}" FontSize="20" />
</Border>
<ContentPresenter x:Name="myPresenter" Grid.Row="1" Grid.ColumnSpan="2" Content="{TemplateBinding Content}" />

Try using a converter
public class AttchedTitleToTitleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value as FrameworkElement).GetValue(WindowDetails.TitleProperty);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Add it to your ResourceDictionary:
<local:AttchedTitleToTitleConverter x:Key="titleConverter"/>
And in the binding:
<Label Content="{Binding RelativeSource={RelativeSource Self}, Converter={DynamicResource titleConverter}}"/>
Hope this helps

Related

Can I make this block of XAML into a reusable "control"?

I have a Grid, and in that grid, I have this:
<StackPanel Grid.Row="2"
Grid.Column="0">
<Grid x:Name="GridButtonItem" Margin="30,0,0,5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Background"
Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="#332a8dd4" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Background"
Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Image Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Margin="3"
Source="{dx:DXImageOffice2013 Image=Windows_32x32.png}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
<TextBlock Grid.Row="0"
Grid.Column="1"
Margin="10,3,3,0"
Text="Application Log" />
<TextBlock Grid.Row="1"
Grid.Column="1"
Margin="10,0,3,3"
Text="C:\Program Files (x86)\ATI Technologies\ATI.ACE\MOM-InstallProxy" />
</Grid>
</StackPanel>
The StackPanel is actually meant to hold many of the GridButtonItem items. Is there a way that I can somehow make a "template" of GridButtonItem and then for each one I want to add to the StackPanel, just set the Image and Text properties?
Something like this (just pseudo-code for demonstration):
<StackPanel>
<Grid Template="myGridItemTemplate">
<Setter Property="Image" Value="img1.png"/>
<Setter Property="Text1" Value="button1 Text"/>
<Setter Property="Text2" Value="button2 Text"/>
</Grid>
<Grid Template="myGridItemTemplate">
<Setter Property="Image" Value="img1.png"/>
<Setter Property="Text1" Value="button1 Text"/>
<Setter Property="Text2" Value="button2 Text"/>
</Grid>
<Grid Template="myGridItemTemplate">
<Setter Property="Image" Value="img1.png"/>
<Setter Property="Text1" Value="button1 Text"/>
<Setter Property="Text2" Value="button2 Text"/>
</Grid>
</StackPanel>
So each one that is added picks up the row/column definitions, and an embedded Image and two TextBlocks. Then I just set the three properties for each one added.
Is this possible?
You can put your grid control into a UserControl and then reuse the UserControl throughout your project. I have a simple example of doing this with a label and Textbox.
here is the XAML:
<UserControl x:Class="TestVision.CustomControls.LabelAndTextbox"
x:Name="parent"
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"
xmlns:local="clr-namespace:TestVision.CustomControls"
mc:Ignorable="d" >
<StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=parent}">
<TextBlock Text="{Binding Path=Label}" Width="{Binding Path=LabelWidth}" VerticalAlignment="Center" TextAlignment="Right" Margin="0,0,10,0" Height="22"/>
<TextBox Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" Width="{Binding Path=TextboxWidth}" IsReadOnly="{Binding Path=TextboxReadOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment="{Binding Path=TextboxHorizontalContentAlgnment}"/>
</StackPanel>
</UserControl>
Any properties that you want to be able to set e.g. your image text etc. must be bound to Dependency Properties in the code behind.
Code behind:
public partial class LabelAndTextbox : UserControl
{
/// <summary>
/// Gets or sets the Label which is displayed next to the field
/// </summary>
public String Label
{
get { return (String)GetValue(LabelContent); }
set { SetValue(LabelContent, value); }
}
/// <summary>
/// Identified the Label dependency property
/// </summary>
public static readonly DependencyProperty LabelContent =
DependencyProperty.Register("Label", typeof(string),
typeof(LabelAndTextbox), new PropertyMetadata(""));
public object Text
{
get { return (object)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(object),
typeof(LabelAndTextbox), new PropertyMetadata(null));
public Double LabelWidth
{
get { return (Double)GetValue(LabelWidthProperty); }
set { SetValue(LabelWidthProperty, value); }
}
public static readonly DependencyProperty LabelWidthProperty =
DependencyProperty.Register("LabelWidth", typeof(Double),
typeof(LabelAndTextbox), new PropertyMetadata());
public Double TextboxWidth
{
get { return (Double)GetValue(TextboxWidthProperty); }
set { SetValue(TextboxWidthProperty, value); }
}
public static readonly DependencyProperty TextboxWidthProperty =
DependencyProperty.Register("TextboxWidth", typeof(Double),
typeof(LabelAndTextbox), new PropertyMetadata());
public bool TextboxReadOnly
{
get { return (bool)GetValue(TextboxReadOnlyProperty); }
set { SetValue(TextboxReadOnlyProperty, value); }
}
public static readonly DependencyProperty TextboxReadOnlyProperty =
DependencyProperty.Register("TextboxReadOnly", typeof(bool),
typeof(LabelAndTextbox), new FrameworkPropertyMetadata());
public HorizontalAlignment TextboxHorizontalContentAlgnment
{
get { return (HorizontalAlignment)GetValue(TextboxHorizontalContentAlgnmentProperty); }
set { SetValue(TextboxHorizontalContentAlgnmentProperty, value); }
}
public static readonly DependencyProperty TextboxHorizontalContentAlgnmentProperty =
DependencyProperty.Register("TextboxHorizontalContentAlgnment", typeof(HorizontalAlignment),
typeof(LabelAndTextbox), new FrameworkPropertyMetadata());
public LabelAndTextbox()
{
InitializeComponent();
}
}
you then will need to add a reference in the XAML file to your UserControl like this:
xmlns:Resource="clr-namespace:ProjectNamespace.FolderContainingYourControl"
Resource is a generic identifier you can call it what you like, you can then reference your control in the like this:
<Resource:LabelAndTextblock x:Name="AddressLine1" Label="{Binding LblTxt_AddressLine1}" Text="{Binding AddressLine1, Mode=TwoWay}" Margin="10,5,0,5" LabelWidth="70" TextWidth="250" TextHeight="60"/>
You could do this with a UserControl (two different ways) or a DataTemplate. Let's go with DataTemplate, because stuicidle already ably demonstrated one UserControl approach.
There are a couple of different ways to do this with a DataTemplate, too.
We're going to do something called an implicit DataTemplate. It's created in Resources, but it has no x:Key property, just a DataType="{x:Type local:GridItemViewModel}" property. What that will do is this: Wherever that DataTemplate is in scope, whenever XAML needs to display a GridItemViewModel and nothing is specifying a template to display it in, it'll use that implicit template.
Clear as mud! Welcome to the XAML learning curve.
ViewModels.cs
using System;
using System.ComponentModel;
using System.Windows.Media;
namespace GridItemAnswer
{
#region ViewModelBase Class
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
#endregion INotifyPropertyChanged
}
#endregion ViewModelBase Class
#region GridItemViewModel Class
public class GridItemViewModel : ViewModelBase
{
#region LabelText Property
private String _labelText = null;
public String LabelText
{
get { return _labelText; }
set
{
if (value != _labelText)
{
_labelText = value;
OnPropertyChanged();
}
}
}
#endregion LabelText Property
#region Path Property
private String _path = null;
public String Path
{
get { return _path; }
set
{
if (value != _path)
{
_path = value;
OnPropertyChanged();
}
}
}
#endregion Path Property
#region ImageSource Property
private ImageSource _imageSource = null;
public ImageSource ImageSource
{
get { return _imageSource; }
set
{
if (value != _imageSource)
{
_imageSource = value;
OnPropertyChanged();
}
}
}
#endregion ImageSource Property
}
#endregion GridItemViewModel Class
}
MainWindow.xaml
<Window
x:Class="GridItemAnswer.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:local="clr-namespace:GridItemAnswer"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
>
<Window.Resources>
<DataTemplate DataType="{x:Type local:GridItemViewModel}">
<StackPanel>
<Grid x:Name="GridButtonItem" Margin="30,0,0,5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#332a8dd4" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Image
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Margin="3"
Source="{Binding Image}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Margin="10,3,3,0"
Text="{Binding LabelText}"
/>
<TextBlock
Grid.Row="1"
Grid.Column="1"
Margin="10,0,3,3"
Text="{Binding Path}"
/>
</Grid>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel>
<ItemsControl>
<local:GridItemViewModel
LabelText="Foo Bar"
Path="c:\foo\bar"
/>
<local:GridItemViewModel
LabelText="Baz Planxty"
Path="c:\baz\planxty"
/>
</ItemsControl>
<Label>
<local:GridItemViewModel
LabelText="A frog walks into a bank asking for a loan"
Path="c:\knick\knack"
/>
</Label>
</StackPanel>
</Grid>
</Window>

how to Detect selected item in ContentControl in wpf

I'm trying to develop a HamburgerMenu. a ContentControl that i restyled it.
my xaml code is something like this :
<Style TargetType="local:HamburgerMenu">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:HamburgerMenu">
<Grid x:Name="mainGrid" Background="{TemplateBinding Background}">
<!--HamburgerMenu button-->
<Border x:Name="border" Background="{TemplateBinding Background}" HorizontalAlignment="Left" VerticalAlignment="Top" Height="40" Width="50">
<ToggleButton x:Name="menuIcon" Background="Red" HorizontalAlignment="Left" VerticalAlignment="Top" Height="40" Width="50" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:HamburgerMenu}}, Path=IsOpen}">
<Path x:Name="path" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Width="30" Fill="{TemplateBinding MenuIconColor}" Data="M2,15.5L22,15.5 22,17.5 2,17.5 2,15.5z M2,10.5L22,10.5 22,12.5 2,12.5 2,10.5z M2,5.5L22,5.5 22,7.5 2,7.5 2,5.5z"/>
</ToggleButton>
</Border>
<!-- HamburgerMenu Items List-->
<ListBox x:Name="listbox" ItemsSource="{TemplateBinding Content}" HorizontalAlignment="Left" Margin="0,40,0,0" VerticalAlignment="Top" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedIndex="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:HamburgerMenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:HamburgerMenuItem">
<Button x:Name="ListBoxItemButton" Command="{TemplateBinding SelectionCommand}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Grid.ColumnSpan="2">
<Grid Background="Transparent" Margin="0" Width="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1">
<TextBlock Text="{TemplateBinding Text}" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" FontFamily="Segoe UI Light" FontSize="18" Foreground="{TemplateBinding Foreground}" TextWrapping="Wrap"/>
</Grid>
<Grid Grid.Column="0">
<Image Source="{TemplateBinding Icon}" Margin="10,5,5,5"/>
</Grid>
</Grid>
</Grid>
<Grid Name="ItemSelectedIndicator" Grid.Column="0" Background="{TemplateBinding SelectionIndicatorColor}" Visibility="Collapsed" />
</Grid>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and this is my HamburgerMenu classes :
public class HamburgerMenu : ContentControl
{
public new List<HamburgerMenuItem> Content
{
get { return (List<HamburgerMenuItem>)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public new static readonly DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof(List<HamburgerMenuItem>), typeof(HamburgerMenu),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
static HamburgerMenu()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(HamburgerMenu), new FrameworkPropertyMetadata(typeof(HamburgerMenu)));
}
public override void BeginInit()
{
Content = new List<HamburgerMenuItem>();
base.BeginInit();
}
}
public class HamburgerMenuItem : ListBoxItem
{
static HamburgerMenuItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(HamburgerMenuItem), new FrameworkPropertyMetadata(typeof(HamburgerMenuItem)));
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(HamburgerMenuItem), new PropertyMetadata(String.Empty));
}
my question is how i can find witch ListBox item is selected in my window where i used my custom Control.
You could add a "SelectedItem" dependency property to your custom control and bind the SelectedItem property of the ListBox in the ControlTemplate to this one:
<!-- HamburgerMenu Items List-->
<ListBox x:Name="listbox" ItemsSource="{TemplateBinding Content}"
SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}"
HorizontalAlignment="Left" Margin="0,40,0,0" VerticalAlignment="Top" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedIndex="0"/>
You then bind your new dependency property to the source property in your window:
<local:HamburgerMenuItem ... SelectedItem="{Binding YourSourceProperty}" />

WPF Custom Control based on grid or nested grid?

I'm learning WPF but I have a lot of Windows Forms background. I want to convert a WinForms custom control in which I did put a label and a textbox (making a TextField), with a property allowing to set percentage of width allocated to the label.
Now, in WPF, I'm a bit lost. Should I create a custom control that inherits from a grid and expose (how ?) the columns definition properties, or should I create a custom control that will "contain" a grid, and expose two properties "LabelWidth" and "ContentWidth", and bind the two column definitions to these properties ? (Thinking these properties would contain 1* and 3*).
Could someone show me an example of such construction to have a place to start?
You could create a UserControl with two dependency properties.
Please refer to the following sample code.
MyUserControl.xaml:
<UserControl x:Class="WpfApplication3.MyUserControl"
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"
xmlns:local="clr-namespace:WpfApplication3"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding LabelWidth, RelativeSource={RelativeSource AncestorType=UserControl}}" />
<ColumnDefinition Width="{Binding ContentWidth, RelativeSource={RelativeSource AncestorType=UserControl}}" />
</Grid.ColumnDefinitions>
<TextBlock Text="..." />
<TextBox Grid.Column="1" />
</Grid>
</UserControl>
MyUserControl.xaml.cs:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty LabelWidthProperty =
DependencyProperty.Register("LabelWidth", typeof(System.Windows.GridLength),
typeof(MyUserControl));
public System.Windows.GridLength LabelWidth
{
get { return (System.Windows.GridLength)GetValue(LabelWidthProperty); }
set { SetValue(LabelWidthProperty, value); }
}
public static readonly DependencyProperty ContentWidthProperty =
DependencyProperty.Register("ContentWidth", typeof(System.Windows.GridLength),
typeof(MyUserControl));
public System.Windows.GridLength ContentWidth
{
get { return (System.Windows.GridLength)GetValue(ContentWidthProperty); }
set { SetValue(ContentWidthProperty, value); }
}
}
Sample usage:
<local:MyUserControl LabelWidth="1*" ContentWidth="5*" />
Dependency Properties Overview: https://msdn.microsoft.com/en-us/library/ms752914(v=vs.110).aspx
I think I managed to achieve what I wanted to do by understanding mm8's code, in particular RelativeSource={RelativeSource AncestorType=UserControl} :
Added a custom control.
FieldText.cs :
public class FieldText : Control
{
static FieldText()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FieldText), new FrameworkPropertyMetadata(typeof(FieldText)));
}
public FieldText()
{
}
public static readonly DependencyProperty LabelLengthProperty =
DependencyProperty.Register("LabelLength", typeof(GridLength),
typeof(FieldText), new UIPropertyMetadata(new GridLength(25, GridUnitType.Star)));
public virtual GridLength LabelLength
{
get { return (GridLength)GetValue(LabelLengthProperty); }
set { SetValue(LabelLengthProperty, value); }
}
public static readonly DependencyProperty ContentLengthProperty =
DependencyProperty.Register("ContentLength", typeof(GridLength),
typeof(FieldText), new UIPropertyMetadata(new GridLength(75, GridUnitType.Star)));
public virtual GridLength ContentLength
{
get { return (GridLength)GetValue(ContentLengthProperty); }
set { SetValue(ContentLengthProperty, value); }
}
}
Generic.xaml :
<Style TargetType="{x:Type controls:FieldText}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:FieldText}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid x:Name="grd" Margin="3px">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=LabelLength, RelativeSource={RelativeSource AncestorType=Control}}" />
<ColumnDefinition Width="{Binding Path=ContentLength, RelativeSource={RelativeSource AncestorType=Control}}" />
</Grid.ColumnDefinitions>
<Label x:Name="label" Grid.Column="0" Content="Field:" />
<TextBox x:Name="textbox" Grid.Column="1" MaxLines="1" TextWrapping="NoWrap" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample usage:
<controls:FieldText x:Name="fld1" LabelLength="25*" ContentLength="75*" />

XAML binding value

I am developing windows phone 8.1 app and I need circular progressbar.
I have this usercontrol code:
<UserControl.Resources>
<Style TargetType="ProgressBar" x:Key="CircularProgressBarStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Grid x:Name="LayoutRoot">
<local:CircularProgressBarViewModel.Attach>
<local:CircularProgressBarViewModel HoleSizeFactor="0.75"/>
</local:CircularProgressBarViewModel.Attach>
<Ellipse Width="{Binding Diameter}" Height="{Binding Diameter}"
HorizontalAlignment="Center" VerticalAlignment="Center"
Stroke="LightGray" Opacity="0.5" Fill="Transparent"
StrokeThickness="10">
</Ellipse>
<local:PiePiece CentreX="{Binding CentreX}" CentreY="{Binding CentreY}"
RotationAngle="0" WedgeAngle="{Binding Angle}"
Radius="{Binding Radius}" InnerRadius="{Binding InnerRadius}"
Fill="Black" Opacity="0.7"/>
<Grid util:GridUtils.RowDefinitions="*,2*,*"
util:GridUtils.ColumnDefinitions="*,2*,*">
<Viewbox Grid.Row="1" Grid.Column="1">
<TextBlock Name="myValue" Text="{myValue value}"
Foreground="WhiteSmoke"
FontWeight="Bold"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Viewbox>
</Grid></Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
How can I change value with the name "myValue" from code behind (for example, from MainPage.xaml.cs) and not from CircularProgressBarViewModel?
If you need to get myValue from your MainPage, where you are using your UserControl you can create DependencyProperty in your control and set any value from page to control.
public sealed partial class YourUserControl: UserControl
{
public static readonly DependencyProperty myValueProperty = DependencyProperty.Register("myValue", typeof(string), typeof(YourUserControl), new PropertyMetadata(string.Empty));
public YourUserControl()
{
this.InitializeComponent();
}
public string myValue
{
get { return (string)GetValue(myValueProperty ); }
set { SetValue(myValueProperty , value); }
}
}
And on the your MainPage like this:
<controls:YourUserControl myValue={Binding YourValue}/>

wp7 TemplateBinding Content not working

I am new in working with wpf and currently I am trying to do the following: I have created a simple ContenctControl (CtrpushPinContent) that contains a TextBlock:
<ContentControl x:Class="CtrpushPinContent" ...
<Grid x:Name="LayoutRoot" Background="{x:Null}">
<Border BorderThickness="3" Name="border1" CornerRadius="15" BorderBrush="#FF070707" Margin="0,0,0,0">
<Border BorderBrush="Silver" BorderThickness="3" Name="border2" CornerRadius="15" Background="#FF413E3E">
<TextBlock Name="textBlock1" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="4" Foreground="White" />
</Border>
</Border>
</Grid>
</ContentControl>
The cs file looks like this:
public partial class CtrpushPinContent : ContentControl
{
public static readonly DependencyProperty CaptionProperty =
DependencyProperty.Register("Text",
typeof(string),
typeof(CtrpushPinContent),
new PropertyMetadata(string.Empty));
public string Text
{
get { return textBlock1.Text; }
set { textBlock1.Text = value; }
}
public CtrpushPinContent()
{
InitializeComponent();
}
}
On the main PhoneApplicationPage I try to do the following:
<phone:PhoneApplicationPage.Resources>
<Style TargetType="my:Pushpin" x:Key="PushpinStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="my:Pushpin">
<Grid x:Name="ContentGrid">
<StackPanel Orientation="Vertical">
<Grid Background="{x:Null}" HorizontalAlignment="Right" MinHeight="31" MinWidth="29">
<LJTileSources:CtrpushPinContent HorizontalAlignment="Right" Text="{TemplateBinding Content}" Margin="4" ContentTemplate="{TemplateBinding ContentTemplate}" />
</Grid>
<Image Source="/WifiHotSpot;component/Images/blackPinNoShadow.png" Width="54" Height="54" HorizontalAlignment="Center"></Image>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Resources>
<Grid>
<my:Map Margin="0,1,0,0" Name="map1" LogoVisibility="Collapsed" Height="576" CredentialsProvider="key" ZoomLevel="2">
<my:Pushpin Style="{StaticResource PushpinStyle}" Content="Test" Location="50.0863762,14.42814" PositionOrigin="BottomLeft"></my:Pushpin>
</my:Map>
</Grid>
However my solution is not working. I cannot see any effect of the
<my:Pushpin Style="{StaticResource PushpinStyle}" Content="Test" .../>
I believe the problem is somewhere in the style declaration:
<LJTileSources:CtrpushPinContent HorizontalAlignment="Right" Text="{TemplateBinding Content}" Margin="4" ContentTemplate="{TemplateBinding ContentTemplate}" />
because when I change it to
<LJTileSources:CtrpushPinContent HorizontalAlignment="Right" Text="TestText" Margin="4" ContentTemplate="{TemplateBinding ContentTemplate}" />
it displays the "TestText" as required.
In your case for solve this problem quickly you need to implement this:
public static readonly DependencyProperty CaptionProperty =
DependencyProperty.Register("Text",
typeof(string),
typeof(CtrpushPinContent),
new PropertyMetadata(string.Empty, OnTextChanged));
public string Text
{
get { return textBlock1.Text; }
set { textBlock1.Text = value; }
}
private static void OnTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
((CtrpushPinContent)sender).textBlock1.Text = (string)e.NewValue;
}
public CtrpushPinContent()
{
InitializeComponent();
}
When you set text in Pushpin template:
<LJTileSources:CtrpushPinContent HorizontalAlignment="Right" Text="{TemplateBinding Content}"
Margin="4" ContentTemplate="{TemplateBinding ContentTemplate}" />
you don't set Text property in your control, you set value of dependency property CaptionProperty, because you registered it with name "Text". So when you set Text from xaml, you set exactly Caption property, not Text property of your control. So you need to create event of changing this dependency property for updating text in textBox1.

Categories