Binding a control completely, not only a property - c#

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.

Related

Binding UWP control to code behind property

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.

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>

Usercontrol databinding property changed MVVM

I am working with WPF and using data binding.
I would like to make a UserControl which has a property that could be used for data binding.
Also, I want to update some other property in the UserControl if the property changed.
For example,
public class MyControl : UserControl
{
....
....
....
....
public ViewStyles CurrentView
{
get { return (ViewStyles)GetValue(CurrentViewProperty); }
set
{
SetValue(CurrentViewProperty, value);
UpdateView();
}
}
public static readonly DependencyProperty CurrentViewProperty = DependencyProperty.Register("CurrentView", typeof(ViewStyles), typeof(ComboView));
....
.....
.....
.....
}
Problems comes:
A ViewModel is used and in which, there is a property ViewStyle which binded to the CurrentView in the above.
Another control combobox is also data-binded with ViewStyle in the ViewModel.
Actually, I want to use a combobox to choose the different view of my control. How to make it possible in MVVM?
I tried the above method. However, the UI (the different ViewStyles of MyControl) didn't change. It only change when I click on it using the mouse.
Thank you.
XAML: (MyControl)
<Views:MyControl Grid.Column="1" Grid.Row="1" Height="505" HorizontalAlignment="Left" Margin="2,0,0,0" Name="comboView1" VerticalAlignment="Top" Width="983"
ViewStyle="{Binding Path=CurrentView}" BorderThickness="5" BorderBrush="Black" ItemsSource="{Binding Path=Images}"
SelectedIndex="{Binding Path=CurrentIndex}" Foreground="White"
</Views:MyControl>
XAML: (ComboBox)
<ComboBox Margin="0,3,1,0" Width="178" HorizontalAlignment="Right" Name="ViewDDBox" FontSize="13" Foreground="#FFF6F3F3" Background="#FF444444"
BorderThickness="2" Height="23" VerticalAlignment="Top" Grid.Column="1"
ItemsSource="{Binding Path=ViewTypes}" IsEnabled="True" SelectedValue="{Binding Path=CurrentView, Mode=TwoWay}">
</ComboBox>
It is supposed that the view (some UI effect) will be changed of MyControl after choosing in the Combobox. But now, it only change when I click on MyControl using mouse.
The UpdateView() in your CurrentView property setter raises a HUGE red flag! You should never have any content other than SetValue in a dependency property setter, as certain aspects of xaml call the SetValue directly instead of going through the property. Always use the coerce property callback (if you want to validate the data before it's set) or the property changed callback (if you want to act after the property is changed, as I show in the example below).
You should do this instead:
public static DependencyProperty CurrentViewProperty =
DependencyProperty.Register("CurrentView", typeof(ViewStyles), typeof(ComboView),
new FrameworkPropertyMetadata(CurrentViewPropertyChanged));
private static void CurrentViewPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyControl mc = (MyControl)d;
mc.UpdateView();
}
Instead of binding the view, why not create a templated control and then bind the control's view to the property on your viewmodel?
You may also have to use data template triggers on your template to get the desired functionality.
Check out this article for help on template basics and this one for a more in depth discussion.

Changing Property of a Style Dynamically

I'm working on a WPF application. I have a Resource Dictionary in which I wrote custom Styles for the ToolTip and for the Button. Actually, for the button i've made two styles.
One of them, has included an image to appear to the left of the content in the buttoon.
<Style x:Key="ButtonImageStyle" TargetType="{x:Type Button}">
........
<TextBlock Margin="5.25,2.417,5.583,5.25" Foreground = White />
<Image x:Name="ButtonImage" Source="/MyProject;component/Images/icoMainMenu01.png" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="-100,0,0,0" Width="16" Height="16"/>
.... </Style
Now, in the MainWindow.xaml i have the following:
<Button Style="{DynamicResource ButtonImageStyle}" x:Name="JustButton" Click="JustButton_Click" Height="50" ToolTip="Press for 1" Content="1" Margin="310,282,400,238" />
I want to be able to change that Image. I will have like 8 buttons and I want each button to have a different image associated with it.
Do you guys have any idea ?
Thanks!
There are various options, from (ab)using properties like the Tag to subclassing or composition in a UserControl, you could also create an attached property.
The cleanest would probably be subclassing though, then you can create a new dependency property for the ImageSource to be used which you then can bind in the default template using a TemplateBinding.
To do the subclassing you can use VS, from the new items choose Custom Control (WPF), this should create a class file and add a base-style to a themes resource dictionary which usually is found in Themes/Generic.xaml. The class would just look like this:
//<Usings>
namespace Test.Controls
{
public class ImageButton : Button
{
public static readonly DependencyProperty ImageProperty =
DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
}
}
Now the theme would be more complicated, you can just copy one of the default templates for a button and paste it into the the default style. Then you only need to add your image somewhere but with this binding:
<Image Source="{TemplateBinding Image}" .../>
When you use this control you will then no longer need to reference a style, as everything is in the default style, there is now a property for the image:
<controls:ImageButton Content="Lorem Ipsum"
Image="Img.png"/>
(To use the Tag you would just stick with the normal button and use a TemplateBinding to the tag and set the Tag of the buttons to the URL)
I forgot to mention another possiblity which uses dynamic resources, it's a bit verbose but very simple, see this answer of mine for an example.

For a user control, how to set the binding of a item template item to a user property?

I have a simple user control, which is essentially just an AutoCompleteBox with some custom logic.
For a specific instance (a collection of Persons), I want it to look like this:
<sdk:AutoCompleteBox Name="myACB" ItemsSource="{Binding People}" FilterMode="StartsWith" MinimumPrefixLength="2" ValueMemberBinding={Binding LastName}>
<sdk:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding LastName}" />
</DataTemplate>
</sdk:AutoCompleteBox.ItemTemplate>
</sdk:AutoCompleteBox>
However, I want to make the data source generic and therefore the display values will be different (ValueMemberBinding and the template TextBlock text). That is why I am making a custom control so I can specify the differences with properties.
I have no problem setting the source with a user control property, but I am having difficulty with the display binding properties. Right now I have:
public static DependencyProperty DisplayMemberProperty = DependencyProperty.Register("DisplayMember", typeof(string), typeof(myAutoComplete), null);
public string DisplayMember
{
get
{ return myACB.ValueMemberPath; }
set
{
myACB.ValueMemberPath = value; // this works fine
// but how can set the text binding for the templated textblock?
}
}
I want the DisplayMember property to be the property name to display for whatever kind of custom collection (persons, cars, etc) I have bound to the AutoCompleteBox.
I don't think I can modify the datatemplate programmatically. Is there a way I can do this with binding (relative source)?
I am not sure if this works, but I think you could bind the text directly to the ValueMemberBinding property and use a converter to get the text out of it...
<TextBlock Text="{TemplateBinding DisplayMember}" />
Thank you for the suggestions.
I was unable to get a solution that I preferred, but my workaround is to just pass in a datatemplate resource as a property and that gets assigned to the autocompletebox itemtemplate.
Define a template:
<DataTemplate x:Key="myCustomDT">
<!-- whatever you want here -->
</DataTemplate>
Create the user control property for it:
public static DependencyProperty DisplayTemplateProperty = DependencyProperty.Register("DisplayTemplate", typeof(DataTemplate), typeof(myAutoComplete), null);
public DataTemplate DisplayTemplate {
get { return myACB.ItemTemplate; }
set { myACB.ItemTemplate = value; }
}
Now:
<local:myAutoComplete DisplayTemplate="{StaticResource myCustomDT}" />
Not the best method, but it will work for now.

Categories