I'm learning UWP User Control and facing the below code:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<local:MyUserControl Username="aaa" Password="bbb" fillcolor="Blue" />
</StackPanel>
</Page>
I have defined a user control with three dependency properties, Username, Password, and fillcolor. The below code shows my user control xaml
<UserControl
x:Name="myctrl"
x:Class="LearningUWP.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<RelativePanel>
<Rectangle Fill="{Binding fillcolor, ElementName=myctrl}" x:Name="Rec" Height="100" RelativePanel.AlignRightWithPanel="True" />
<TextBlock Text="Username_lbl" RelativePanel.AlignRightWithPanel="True" TextAlignment="Center" RelativePanel.Below="Rec" x:Name="Username_lb" Margin="0,50,0,0" RelativePanel.AlignLeftWithPanel="True" />
<TextBox x:Name="Username_input" RelativePanel.Below="Username_lb" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignLeftWithPanel="True" Margin="0,20,0,0" Text="{Binding Username, ElementName=myctrl}" ></TextBox>
<TextBlock Text="Password_lbl" x:Name="Password_lb" RelativePanel.AlignRightWithPanel="True" TextAlignment="Center" RelativePanel.Below="Username_input" RelativePanel.AlignLeftWithPanel="True" Margin="0,20,0,0" ></TextBlock>
<TextBox x:Name="Password_input" RelativePanel.Below="Password_lb" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignLeftWithPanel="True" Margin="0,20,0,0" Text="{Binding Password, ElementName=myctrl}" ></TextBox>
</RelativePanel>
</UserControl>
and the code-behind:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace LearningUWP
{
public sealed partial class MyUserControl : UserControl
{
public MyUserControl()
{
this.InitializeComponent();
}
public string Username
{
get { return (string)GetValue(UsernameProperty); }
set { SetValue(UsernameProperty, value); }
}
public static readonly DependencyProperty UsernameProperty =
DependencyProperty.Register("Username", typeof(string), typeof(MyUserControl), null);
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(MyUserControl), null);
public string fillcolor
{
get { return (string)GetValue(fillcolorProperty); }
set { SetValue(fillcolorProperty, value); }
}
public static readonly DependencyProperty fillcolorProperty =
DependencyProperty.Register("fillcolor", typeof(string), typeof(MyUserControl), null);
}
}
The Username and Password are working as I can see "aaa" and "bbb" on my screen, but the color is not working. How to solve it?
UPDATE1
I modified the fillcolor property to the below code:
public Brush fillcolor
{
get { return (Brush)GetValue(fillcolorProperty); }
set { SetValue(fillcolorProperty, value); }
}
public static readonly DependencyProperty fillcolorProperty =
DependencyProperty.Register("fillcolor", typeof(Brush), typeof(MyUserControl), null);
But it's still not working.
UPDATE2
I updated the MainPage.xaml shown in the below:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<SolidColorBrush x:Key="MyBlueColor" Color="#0000FF"/>
</Page.Resources>
<StackPanel>
<local:MyUserControl Username="aaa" Password="bbb" fillcolor="{StaticResource MyBlueColor}" />
</StackPanel>
</Page>
But it's still not working.
Your binding seems correct, your problem is in the Type of your 'fillcolor' property.
You are binding it as a string, whereas you should bind it as a Brush
public Brush fillcolor
{
get { return (Brush)GetValue(fillcolorProperty); }
set { SetValue(fillcolorProperty, value); }
}
public static readonly DependencyProperty fillcolorProperty =
DependencyProperty.Register("fillcolor", typeof(Brush), typeof(MyUserControl), null);
The Fill property requires a Brush to work properly as you can see in here Shape.Fill
I forgot to mention that you don't need to specify the element name in this case as you are using your code behind as a 'ViewModel', so, the code below will do the trick for you:
<Rectangle Fill="{x:Bind fillcolor}" x:Name="Rec" Height="100" RelativePanel.AlignRightWithPanel="True" />
Furthermore, you need to specify the Brush in your page's resources as a solid color brush, so you could write:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<SolidColorBrush x:Key="MyBlueColor" Color="#0000FF"/> <!-- or Blue -->
</Page.Resources>
<StackPanel>
<local:MyUserControl Username="aaa" Password="bbb" fillcolor="{StaticResource MyBlueColor}" />
</StackPanel>
</Page>
And, according to difference-between-binding-and-xbind
We need to use x:Bind Binding does not support framework elements.
Related
I want to use a custom UserControl in an ItemsControl but it is not working.
A minimalistic example:
Project.Controls.UserControl1.xaml
<UserControl x:Class="Project.Controls.UserControl1"
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:Project.Controls"
mc:Ignorable="d"
Height="50" Width="100">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:UserControl1}}, Path=Text1}"/>
<Label Grid.Column="1" Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:UserControl1}}, Path=Text2}"/>
</Grid>
</UserControl>
Project.Controls.UserControl1.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace Project.Controls
{
/// <summary>
/// Interaktionslogik für UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string Text1
{
get { return (string)GetValue(Text1Property); }
set { SetValue(Text1Property, value); }
}
public readonly DependencyProperty Text1Property =
DependencyProperty.Register("Text1", typeof(string), typeof(UserControl1));
public string Text2
{
get { return (string)GetValue(Text2Property); }
set { SetValue(Text2Property, value); }
}
public readonly DependencyProperty Text2Property =
DependencyProperty.Register("Text2", typeof(string), typeof(UserControl1));
}
}
Project.Controls.UserControl2.xaml
<UserControl x:Class="Project.Controls.UserControl2"
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:Project.Controls.Elements"
mc:Ignorable="d"
Height="450" Width="800">
<Grid Background="Gray">
<ItemsControl x:Name="MyItemControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControl1 Text1="{Binding Text1}" Text2="{Binding Text2}" Margin="10"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
Project.Controls.UserControl2.xaml.cs
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
MyItemControl.ItemsSource = new List<MyListItem>()
{
new MyListItem("a", "b"),
new MyListItem("a", "b"),
new MyListItem("a", "b"),
new MyListItem("a", "b"),
new MyListItem("a", "b"),
new MyListItem("a", "b"),
new MyListItem("a", "b"),
};
}
}
here i have used the class MyListItem:
public class MyListItem
{
public string Text1 { get; set; }
public string Text2 { get; set; }
public MyListItem(string text1, string text2)
{
Text1 = text1;
Text2 = text2;
}
}
In the mainWindow I use UserControl2 like this:
<Window x:Class="Project.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:Project"
xmlns:controls="clr-namespace:Project.Controls"
mc:Ignorable="d"
Title="Test" Height="800" Width="1280" >
<Grid>
<controls:UserControl2/>
</Grid>
</Window>
Now my problem: I either get the error
System.Windows.Markup.XamlParseException: ""Binding" cannot be set for the "Text1" property of type "UserControl1". "Binding" can be set only for a DependencyProperty of a DependencyObject."
The identifier field of a dependency property must be declared as a static field:
public static readonly DependencyProperty Text1Property =
DependencyProperty.Register(
nameof(Text1),
typeof(string),
typeof(UserControl1));
For details see Custom Dependency Properties.
I want to create a Custom User control (UserControl) with custom property (MyLabel) in WPF using C# without writing any code behind. But my custom property MyLabel is inaccessible in MainWindow.xaml when I'm using my custom control. What is the problem in my code? If my implementation is wrong then how to achieve this?
UCControl.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public class UCControl:UserControl
{
public String MyLabel
{
get { return (String)GetValue(MyLabelProperty); }
set { SetValue(MyLabelProperty, value); }
}
public static readonly DependencyProperty MyLabelProperty =
DependencyProperty
.Register(
"MyLabel",
typeof(string),
typeof(UCControl),
new PropertyMetadata(""));
public UCControl()
{
MyLabel = "default label";
}
}
}
UserControl1.xaml
<UserControl x:Class="WpfApp1.UserControl1"
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:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.DataContext>
<local:UCControl/>
</Grid.DataContext>
<TextBlock Text="{Binding MyLabel}" FontSize="18"/>
</Grid>
</UserControl>
MainWindow.xaml
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid >
<local:UserControl1 MyLabel="Hello World"/>
</Grid>
</Window>
The expression
<local:UserControl1 MyLabel="Hello World"/>
requires that MyLabel is a property of the UserControl1 class.
You have to declare the property of the class declaration of UserControl1, i.e. in the file UserControl1.xaml.cs:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public static readonly DependencyProperty MyLabelProperty =
DependencyProperty.Register(
nameof(MyLabel),
typeof(string),
typeof(UserControl1));
public string MyLabel
{
get { return (string)GetValue(MyLabelProperty); }
set { SetValue(MyLabelProperty, value); }
}
}
You would bind to that property in the UserControl's XAML by
<TextBlock Text="{Binding MyLabel,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
Hello i am trying to initialize usercontrol with bacground which is binded in viewmodel. In model color is set but dependency property does not take it.
HeaderCropper xaml :
<UserControl x:Class="x.CustomControls.x"
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:converters="clr-x.Converters"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
Width="{Binding CropperWidth,ElementName=HeaderCropper}"
Height="{Binding CropperHeight,ElementName=HeaderCropper}"
x:Name="HeaderCropper">
<Thumb x:Name="CroppableArea" BorderThickness="1" Grid.Column="0" Grid.Row="0" Background='{Binding CropperColor}' BorderBrush="Black" Opacity="0.2"
HeaderCropper class :
public static DependencyProperty ColorProperty;
static HeaderCroper()
{
ColorProperty = DependencyProperty.Register("CropperColor",
typeof(Brush), typeof(HeaderCroper), new FrameworkPropertyMetadata(null));
}
public Brush CropperColor
{
get { return (Brush)GetValue(ColorProperty); }
set
{
SetValue(ColorProperty, value);
}
}
HeaderCropper binding :
<DataTemplate>
<custom:HeaderCroper Panel.ZIndex="1" Width="50" Height="50" CropperHeight="{Binding Height,Mode=TwoWay,NotifyOnTargetUpdated=True}"
CropperWidth="{Binding Width,Mode=TwoWay,NotifyOnTargetUpdated=True}"
MaxCropperHeight="{Binding ElementName=Image,Path=RenderSize.Height}"
MaxCropperWidth="{Binding ElementName=Image,Path=RenderSize.Width}"
InfoCommand="{Binding InfoCommand}"
InfoCommandParameter="{Binding Id}"
DeleteCropperCommand="{Binding DeleteCommand}"
DeleteCropperCommandParameter="{Binding Id}"
CropperLeft="{Binding CropperLeft,Mode=TwoWay,NotifyOnTargetUpdated=True}"
CropperTop="{Binding CropperTop,Mode=TwoWay,NotifyOnTargetUpdated=True}"
MainCanvas ="{Binding ElementName=CropperCanvas,NotifyOnTargetUpdated=True}"
Canvas.Left="0"
CropperColor="{Binding CropperColor,Mode=TwoWay,NotifyOnTargetUpdated=True}"
/>
</DataTemplate>
As you can see CropperColor parameter is passed but header cropper is ignoring it and not setting color. Any ideas?
UPDATE:
As I debug on private method key press I see that color is set but it is null while usercontroll is initializing.
Well I made my custom usercontrol which is "simply" a combination of a label and a textbox.
<UserControl x:Class="testit.LabelTextBox"
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"
d:DesignHeight="30" d:DesignWidth="300">
<DockPanel LastChildFill="False">
<TextBox x:Name="textBox" TextWrapping="Wrap" DockPanel.Dock="Right" VerticalAlignment="Center" Text="{Binding TextBoxText}" />
<Label x:Name="label" DockPanel.Dock="Right" Target="{x:Reference textBox}" HorizontalAlignment="Right" VerticalAlignment="Center" Content="Label Text"/>
</DockPanel>
</UserControl>
I then created a usercontrol class with the dependecy property:
using System.Windows;
using System.Windows.Controls;
namespace simtest
{
/// <summary>
/// Interaction logic for LabelTextBox.xaml
/// </summary>
public partial class LabelTextBox : UserControl
{
public string TextBoxText {
get { return (string)GetValue(TextBoxTextProperty); }
set { SetValue(TextBoxTextProperty, value); }
}
public readonly static DependencyProperty TextBoxTextProperty =
DependencyProperty.Register("TextBoxTextProperty",
typeof(string), typeof(LabelTextBox), new UIPropertyMetadata(null));
public LabelTextBox() {
InitializeComponent();
DataContext = this;
}
}
}
Now this "works" as in that it compiles. And if I use above control as:
<local:LabelTextBox TextBoxText="foobar"></local:LabelTextBox>
It will show correctly - while running -.
However I need this for each and every element of the textbox I wish to be able to adapt - height width etc etc. This isn't really ideal: can I make it so that I can just edit the LabelTextBox' TextBox directly?
For my project I'm adding an attached property to my controls using DependencyProperty.
It works, but I would like to have my property exposed in the VisualStudio Properties Window.
I'm not creating any UserControl, because I want all my standard controls to have this property.
Also, I don't want to use the existing Tag property as in the future I will have more properties to add.
Is this possible? How it can be done?
My XAML:
<Window x:Class="Wpf_CustomPropertyTest.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:Wpf_CustomPropertyTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="button1" Content="Button 1" local:Extensions.MyTestProp="Hello 1!" Click="button_Click" HorizontalAlignment="Left" Height="39" Margin="36,36,0,0" VerticalAlignment="Top" Width="171" />
<Button x:Name="button2" Content="Button 2" local:Extensions.MyTestProp="Hello 2!" Click="button_Click" HorizontalAlignment="Left" Height="39" Margin="36,90,0,0" VerticalAlignment="Top" Width="171" />
</Grid>
</Window>
My code-behind:
using System.Windows;
namespace Wpf_CustomPropertyTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Extensions.GetMyTestProp((UIElement)sender));
}
}
public class Extensions
{
public static readonly DependencyProperty MyTestPropProperty = DependencyProperty.RegisterAttached("MyTestProp", typeof(string), typeof(Extensions), new PropertyMetadata(default(string)));
public static void SetMyTestProp(UIElement element, string value)
{
element.SetValue(MyTestPropProperty, value);
}
public static string GetMyTestProp(UIElement element)
{
return (string)element.GetValue(MyTestPropProperty);
}
}
}