Binding UWP control to code behind property - c#

I am developing UWP app and I created new user control and I want to bind it to dependency property in the control's code behind (without the datacontext).
Code Behind:
public Brush Fill
{
get { return (Brush)GetValue(FillProperty); }
set { SetValue(FillProperty, value); }
}
// Using a DependencyProperty as the backing store for Fill. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FillProperty =
DependencyProperty.Register("Fill", typeof(Brush), typeof(MyControl), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
XAML:
...
<Grid>
<Path Fill="{Binding ????}" Stretch="Fill">
...
</Path>
</Grid>
I want that my path's fill property will bind to the property Fill from code behind (the data context should hold different data so I can't use it here)
How can I do that in UWP?

x:Bind would work perfectly on this. Note x:Bind will be looking for properties, methods & events defined in your XAML's code-behind. It's a more performant binding than ElementName.
<Path Fill="{x:Bind Fill, Mode=OneWay}" />

You should be able to use the ElementName property of a binding to circumvent the data context, just as normal WPF allows you to do.
If the property is part of the user control you'll need to assign a name via x:Name to your user control in xaml to access it
<UserControl [...] x:Name="Control"...`
Then use something like{Binding ElementName=Control, Path=Fill}, as long as Fill is a property of your user control.

Related

DataTemplate in Custom Control

I have a custom control (NavigationContentCtrl) for displaying various Views/ViewModels.
In the Resources of the custom control, the data template for a given ViewModel points to the corresponding View (for simplicity I have included only one VM/V pair):
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:SampleMainContentViewModel}">
<views:SampleMainContentView/>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
There is also a ContentPresenter bound to an underlying Dependency Property:
<ContentPresenter Grid.Column="1"
Content="{Binding CurrentContentViewModel,
RelativeSource={RelativeSource TemplatedParent}}"/>
In the backing Dependency Property (CurrentContentViewModel), if I instantiate a VM in the property, then the control finds the corresponding View and displays it correctly.
For example, using "SampleMainContentViewModel", this works fine:
// Using a DependencyProperty as the backing store for CurrentContentViewModel. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentContentViewModelProperty =
DependencyProperty.Register("CurrentContentViewModel", typeof(object),
typeof(NavigationContentCtrl),
new FrameworkPropertyMetadata(new SampleMainContentViewModel(),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
However, if I try to set the VM when I am using an instance of the custom control (e.g. in the MainWindow):
<Grid>
<controls:NavigationContentCtrl
CurrentContentViewModel="{x:Type vm:SampleMainContentViewModel}"
/>
</Grid>
Then all I get is the string name of the VM:
Many thanks to anyone who can help.
Thanks to #Clemens for prompting my brain-reboot.
In the instantiation of the control (e.g. in the MainWindow), the control's dependency property should be bound to property:
<Grid>
<controls:NavigationContentCtrl
CurrentContentViewModel="{Binding ContentViewModel}"
/>
</Grid>
The property, ContentViewModel, is declared and set in the underlying MainWindowViewModel:
public object ContentViewModel { get; set; } = new SampleMainContentViewModel();
Further, the Dependency property can be simplified to remove the BindsTwoWayByDefault syntax and the ContentPresenter's Content property can be set using the simpler TemplateBinding syntax.

Windows 10 UWP UserControl with customizable content

I want to make a user control in Windows 10 UWP with changing content.
I know how to make a simple user control, but I need a user control like this:
<Controls:UserControl x:Name="Usercontrol1" Margin="0,10,0,0" Grid.Row="1">
<Controls:UserControl.MainContent>
<Grid x:Name="Content">
//Items are here
</Grid>
</Controls:UserControl.MainContent>
</Controls:UserControl>
I have Grid in my user control that is empty and I want to give this grid different items in every page. I want a way to set a grid for my user control in the page, then add this grid to my user control instead of that empty grid.
Is there any way to do this?
To do this, you need to create a MainContent dependency property in the code-behind of your user control and display it using a ContentPresenter.
Suppose your user control is defined in MyControl.xaml and MyControl.xaml.cs.
Creating the MainContent dependency property
Inside the UserControl class definition in UserControl.xaml.cs add the following:
public static readonly DependencyProperty MainContentProperty =
DependencyProperty.Register(
"MainContent",
typeof( object ),
typeof( MyControl ),
new PropertyMetadata( default( object ) ) );
public object MainContent
{
get { return ( object ) GetValue( MainContentProperty ); }
set { SetValue( MainContentProperty, value ); }
}
As a shortcut in Visual Studio you can write propdp or dependencyProperty (depending on your version) and press the Tab key to automatically fill out a code snippet for the whole property.
Adding ContentPresenter
Inside the MyControl.xaml find the place where you want to display the content and put a ContentPresenter there with a binding to the MainContent property.
There are several ways to do this.
The newest technique with x:Bind syntax
<ContentPresenter Content="{x:Bind MainContent}" />
Using binding with element - here you will need to add a x:Name attribute to the UserControl element itself, call it RootControl for example, and then create the binding like this:
<ContentPresenter Content="{Binding MainContent, ElementName=RootControl}" />
Using binding with DataContext - in the constructor of the UserControl in MyControl.xaml.cs you can set the DataContext - this.DataContext = this; and then write simply:
<ContentPresenter Content="{Binding MainContent}" />
Usage
Now your UserControl is ready and you can use it like this:
<local:MyControl>
<local:MyControl.MainContent>
<!-- some content :-) -->
<Image Source="Assets/LockScreenLogo.png" Width="100"/>
</local:MyControl.MainContent>
</local:MyControl>

Setting Image Source in a UserControl Button

i got an userControl, and i want to set the image button from the page in which userControl is included.
If i set my button image in the usercontrol in this way it works but i can't change.
<Button blablabla>
<Image Source="../../../Assets/truck-512.png"/>
</Button>
So i define a property from the codebehind
public ImageSource ButtonSource
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
// Using a DependencyProperty as the backing store for Source. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(ImageSource), typeof(TruckFormUC),null);
and in my userContol xaml i set my image as following
<Image x:Name="imgIcon" Source="{Binding Path=ButtonSource}"/>
than i use my userControl in my page and i try to set the image source, but it doesn't work
<UC:TruckFormUC x:Name="truckForm"
ButtonSource="../../../Assets/truck-512.png"/>
Thanks a lot
The userControl and the page are in the same folder.
Your binding is looking for ButtonSource property on the DataContext object. If you want to bind to your UserControl you should use relative binding.
<Image x:Name="imgIcon" Source="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType=UC:TruckFormUC},
Path=ButtonSource}"/>
See RelativeSource markup extension MSDN article for more info
You should also be able to use element binding.
<Image x:Name="imgIcon" Source="{Binding ElementName=truckForm, Path=ButtonSource}"/>

Binding a control completely, not only a property

I'm developing a Windows Phone 8 application with an User Control.
This user control has a border, and I want to create a DependencyProperty to access this border:
public partial class CustomOptionButton : UserControl
{
public Border OuterBorder
{
get
{
return (Border)GetValue(OuterBorderProperty);
}
set
{
SetValue(OuterBorderProperty, value);
}
}
public readonly DependencyProperty OuterBorderProperty =
DependencyProperty.Register("OuterBorder", typeof(Border), typeof(CustomOptionButton), null);
But I don't know how I can bind this property in XAML.
When I have bind a TextBlock.Text, I did this on XAML:
<TextBlock x:Name="CustomText" Text="{Binding ButtonText, ElementName=userControl}" />
But, How can I do the same with the entire Border?
<Border x:Name="OutBorder" BorderBrush="White" BorderThickness="2" Margin="0">
I will need to change the BorderBrush and the BorderThickness (and maybe another properties), so I have thought that I could have only one property instead of three or four.
In this case, you need to create for each type of separate property, because to use one property Border need to create a separate Control like this:
public сlass MyBorderControl : Border
{
// Your implementation of Control
}
If you want to create a property that could be used for any Control, in WPF has attached properties:
MSDN: Attached properties overview
and used like this:
<Canvas>
<Button Canvas.Left="50">Hello</Button>
</Canvas>
In this case, Canvas.Left attached property used for the Button class.

How to add variable Image on User Control

I'm trying to have a user control where an image is passed in from its containing element. The purpose is so that I can reuse a common set of visual elements while only changing the image. For example:
The control usage:
<DataTemplate DataType={x:Type myType}>
<local:MyControl PlotIconSource="..\Images\Scatter.png"/>
</DataTemplate>
The Image inside the control
<UserControl x:Class="MyControl">
<Image Source="{Binding PlotIconSource}"/>
</UserControl>
Finally the dependency property for PlotIconSource in the code-behind for MyControl.xaml.cs.
public ImageSource PlotIconSource
{
get { return (ImageSource)GetValue(PlotIconSourceProperty); }
set { SetValue(PlotIconSourceProperty, value); }
}
public static readonly DependencyProperty PlotIconSourceProperty =
DependencyProperty.Register(
"PlotIconSource",
typeof(ImageSource),
typeof(PlotHeader),
new UIPropertyMetadata());
I'm sure I've missed something along the way so any help would be appreciated.
You might want to bind via RelativeSource or with ElementName:
<UserControl x:Class="MyControl" Name="control">
<Image Source="{Binding PlotIconSource, ElementName=control}"/>
</UserControl>
(Do not set the DataContext, it will be invisible from the outside and mess with bindings meant for an inherited DataContext)
Looks right to me, are you getting an error message or something?

Categories