WPF Adding control to a specific area of UserControl dynamically - c#

Good afternoon,
I seem to be having a simple issue with WPF.
After googling for few good hours, I couldn't find anything that would resemble what I'm looking for.
To put simply, I'm looking for a way to define an area in my custom UserControl like this:
<UserControl>
<TemplateArea x:Name="FormControls">
</TemplateArea>
</UserControl>
Then do this inside Window, Panel, etc. that uses my custom control:
<TheUserControl>
<TemplateArea x:Name="FormControls">
<TextBox/>
</TemplateArea>
</TheUserControl>
.. and as a result, TextBox will be directly pasted inside of my custom control.

One solution would be to create a dependency property that holds an array of controls, and inside your control you bind it to an ItemsControl:
child.xaml
<UserControl x:Name="RootControl">
<...> <!-- your other UI -->
<ItemsControl ItemSource="{Binding Items, ElementName=RootControl}" />
<!-- style the items and/or panel as you wish -->
</...>
</UserControl>
child.cs
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items", typeof(Observable<UIElement>), typeof(Child),
new PropertyMetadata(new Observable<UIElement>()));
host.xaml
<Page>
<...>
<my:Child>
<my:Child.Items>
<TextBox/>
<CheckBox/>
</my:Child.Items>
</my:Child>
</...>
</Page>

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>

StackPanel with User Controls in another User Control in Xaml Windows Phone

How Can I add child items to StackPanel in UserControl from C# code? Should I create something like DependencyProperty for it?
As it is easy to set Properties like Text for TextBlock in my UserControl, I have no idea how can I add items to StackPanel when using CodeBehind to do it dynamicaly.
StackPanel are only meant to be used for the most basic layout situations. It is far better using some kind of ListBox or ItemsControl depending on your requirements. You could add a collection DependencyProperty to your UserControl and do something like this:
In UserControl:
<ItemsControl ItemsSource="{Binding YourCollectionDependencyProperty, RelativeSource={
RelativeSource AncestorType={x:Type YourPrefix:YourUserControl}}}" ... />
Then you could data bind another collection property to the UserControl from outside the control:
Outside UserControl:
<YourPrefix:YourUserControl YourCollectionDependencyProperty="{Binding Items}" ... />
Then adding new items to be displayed in the UserControl is as simple as adding items to the Items collection:
Items.Add(someNewObject);
Please read the Data Binding Overview page on MSDN for further information on data binding.
Yes you can do something like this (this is just a sample):
TextBlock printTextBlock = new TextBlock();
printTextBlock.Text = "Hello, World!";
//MainStackPanel below is the name given to your control in xaml
MainStackPanel.Children.Add(printTextBlock);
Sources:
Programatically Adding Items to StackPanel

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?

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.

Categories