expose a field in wpf user control for external use - c#

I am very new to wpf and I would like to create a simple user control that consists of a textblock and a textbox so that I can reuse it. However, I do not really know how to bind the content of the textblock so that it can be set from outside and expose the textbox so that it could be bound to other field from the outside calling xaml.
The following is the code for my user control
<UserControl x:Class="WPFLib.UserControlLibs.TextBoxUsrCtrl"
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:WPFLib.UserControlLibs"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="300">
<StackPanel Orientation='Horizontal'
Width='{Binding ActualWidth, ElementName=parentElementName}'
Height='{Binding ActualWidth, ElementName=parentElementName}'>
<Grid HorizontalAlignment='Stretch'>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='1*' />
<ColumnDefinition Width='1*' />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text='{Binding Text, ElementName=parentElementName}'
Background='Aqua'
Grid.Column='0'
Grid.Row='0' />
<TextBox x:Name='UserTxBox'
Grid.Column='1'
Grid.Row='0'
Background='Red'
HorizontalAlignment='Stretch'
Text='this is a test to see how it works' />
</Grid>
</StackPanel>
</UserControl>
How do I expose the Text from the TextBlock and TextBox so that it could be set and retrieved from the calling xaml?
For example
<Window x:Class="TestWPF.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:TestWPF"
xmlns:controls='clr-namespace:WPFLib.UserControlLibs'
` mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525"
WindowState='Maximized'
FontSize='18'>
<StackPanel>
<controls:TextBoxUsrCtrl Width='500' HorizontalAlignment='Left' **Text='NEED TO SET THE TEXT BLOCK HERE'**/>
</StackPanel>
</Window>

You should give it two dependency properties, one for each of the two text properties you want to expose (this is a horrible amount of boilerplate; I use Visual Studio's snippet feature to generate it all). Then in the UserControl XAML, you bind control properties to those.
public partial class TextBoxUsrCtrl : UserControl
{
public TextBoxUsrCtrl()
{
InitializeComponent();
}
#region Text Property
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(String), typeof(TextBoxUsrCtrl),
new FrameworkPropertyMetadata(null) {
// It's read-write, so make it bind both ways by default
BindsTwoWayByDefault = true
});
#endregion Text Property
#region DisplayText Property
public String DisplayText
{
get { return (String)GetValue(DisplayTextProperty); }
set { SetValue(DisplayTextProperty, value); }
}
public static readonly DependencyProperty DisplayTextProperty =
DependencyProperty.Register(nameof(DisplayText), typeof(String), typeof(TextBoxUsrCtrl),
new PropertyMetadata(null));
#endregion DisplayText Property
}
XAML. I simplified this so the layout works as I think you intended.
Note how the bindings use RelativeSource={RelativeSource AncestorType=UserControl} to bind to the dependency properties we defined above on the UserControl. By default, Binding will bind to properties of UserControl.DataContext, but we're not using that. The reason is that if we set UserControl.DataContext here, that will break the viewmodel property bindings in the final XAML fragment at the end of this answer. Those bindings will look for those properties on our control. There are workarounds but it gets ugly. The way I've done it here is best because it never breaks anybody's assumptions about DataContext inheritance.
<UserControl
x:Class="WPFLib.UserControlLibs.TextBoxUsrCtrl"
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:WPFLib.UserControlLibs"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="300"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='*' />
<ColumnDefinition Width='*' />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
Text='{Binding DisplayText, RelativeSource={RelativeSource AncestorType=UserControl}}'
Background='Aqua'
Grid.Column='0'
Grid.Row='0'
/>
<TextBox
x:Name='UserTxBox'
Grid.Column='1'
Grid.Row='0'
Background='Red'
HorizontalAlignment='Stretch'
Text='{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}'
/>
</Grid>
</UserControl>
Usage in window, bound to viewmodel properties:
<local:TextBoxUsrCtrl
Text="{Binding TestText}"
DisplayText="{Binding ShowThisText}"
/>
Lastly, I'm not sure what you were getting at with ElementName=parentElementName. If that's meant to be a reference to a parent control, you can't do that, and it wouldn't be a good idea if you could. You wouldn't want a UserControl constrained by a requirement that a parent control must have a particular name. The answer to that requirement is simply that controls in XAML are only responsible for sizing themselves if they have a fixed size. If they should size to the parent, the parent is always the one responsible for that. So if you want to size two instances of TextBoxUsrCtrl to two different parents, that's fine. Each parent sizes its own children as it pleases.

Related

Modify textblock of a UserControl from another UserControl WPF

i have a UserControl that contains a TextBox now i am loading another UserControl that contains a TextBlock .When the button is clicked, I want to assign value entered in TextBox to TextBlock of another control that is loaded. How can i do this ?
Main UserControl
<UserControl x:Class="IntelliVentory.UserControls.CategoryControl"
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="670" d:DesignWidth="1100">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Name="CategoryNameBox" Width="350" />
<Button Grid.Row="1" Click="AddCategoryFunc">Load Another Control</Button>
<Grid Grid.Row="2" Name="CategoriesWraper"></Grid>
</Grid>
</UserControl>
Another UserControl
<UserControl x:Class="IntelliVentory.UserControlModules.CategoryModule"
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:IntelliVentory.UserControlModules"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock Name="CategoryName" FontSize="12" FontWeight="Thin">Category Name Here</TextBlock>
</Grid>
</UserControl>
Main UserControl.cs
Loading another UserControl.
private void AddCategoryFunc(object sender, RoutedEventArgs e)
{
UserControl categoryMod = new CategoryModule();
CategoriesWraper.Children.Add(categoryMod);
}
You want to have something like
categoryMod.CategoryNameValue = categoryControl.CategoryNameValue;
So you need to define two properties, one CategoryNameValue property with which you get the Text value of the TextBox, and one CategoryNameValue property with which you can set the Text property of the TextBlock.
Define this property in the CategoryControl class,
public string CategoryNameValue { get { return CategoryNameBox.Text; }
And this in CategoryModule class,
public string CategoryNameValue { set { CategoryName.Text = value; }
And you can start using them in your code.
You can define them as Dependency Properties instead of plain CLR properties, and then look to use data binding. With data binding both user controls can be bound to the same data model so their values are synced automatically.
Edit:
Turns out you can access a UserControl's child elements from outside as if they are public fields. That is, you can write code like this without having to define new properties
CategoryModule categoryMod = new CategoryModule();
categoryMod.CategoryName.Text = CategoryNameBox.Text;
CategoriesWraper.Children.Add(categoryMod);

Update the TextBox.Text in Usercontrol from everywhere

I'm facing an issue that seems recurrent and with a lot of solutions but, I apologize, I cannot/not able apply in my case. Let me summarize the topology: I have a main windows (MainWindow) with a grid and, in the bottom cell I put an user control written by me (UC_StatusMonitor) with a textbox inside the user control (LBL_CONN_Message) where I want to update with result of operations (e.g. "Connected to device X", "Impossible to read data from Y", "Missing fields" etc etc). This is basically used to inform the user if something is right or wrong. I understood I have to use Dependancy to solve this issue but my implementation doesn't work (for sure I missed something).
Let me show the code:
MainWindows.xaml
<Window x:Class="LUX.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:LUX"
mc:Ignorable="d"
Title="LUX" Name ="MainForm" Height="600" Width="800" MinHeight="600" MinWidth="800">
<Border Padding="10">
<Grid Name="Main_Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<!-- others controls .... -->
<!-- Monitor -->
<StackPanel Name="Stack_Monitor" Grid.Row="2" Grid.Column="1">
<Grid Name="BottomBar" Height="20">
<local:UC_StatusMonitor Height="100" Grid.Row="2" Grid.Column="1"/>
</Grid>
</StackPanel>
</Grid>
</Border>
</Window>
Then the code for the Control
UC_StatusMonitor.xaml
<UserControl x:Class="LUX.UC_StatusMonitor"
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:LUX"
mc:Ignorable="d"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
d:DesignHeight="20" d:DesignWidth="300">
<Grid Name="UCR_Base" Background="White">
<WrapPanel>
...
<TextBox Name="LBL_CONN_Message" Margin = "10 0 0 0" VerticalAlignment="Center" IsReadOnly="True" BorderThickness="0" Text="{Binding MyTextProperty, ElementName=control}"/>
...
</WrapPanel>
</Grid>
</UserControl>
UC_StatusMonitor.xaml.cs
namespace LUX {
/// <summary>
/// Interaction logic for StatusMonitor.xaml
/// </summary>
public partial class UC_StatusMonitor : UserControl
{
Button[] MenuButtons;
//// The dependency property which will be accessible on the UserControl
public static readonly DependencyProperty MyTextPropertyProperty = DependencyProperty.Register("MyTextProperty", typeof(string), typeof(UC_StatusMonitor), new UIPropertyMetadata(String.Empty));
public string MyTextProperty
{
get { return (string)GetValue(MyTextPropertyProperty); }
set { SetValue(MyTextPropertyProperty, value); }
So, I'm expecting that, everywhere (in all the classes into the workspace, I declared a status monitor static object), I should use an instruction like
MyTextProperty = "Connected";
and then see this message on the textbox into user control.
Obviously, doesn't happen :(
Thanks and best regards
I have managed to get the UserControl to work with Binding.
Here is how I have done it:
UserControlWithBinding.xaml:
<UserControl x:Class="SO_app.UserControlWithBinding"
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:SO_app"
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="300">
<Grid Name="IAmGroot"> <!-- Name this grid as you want as this is what we will use for internal Binding -->
<TextBlock Text="{Binding Status}"/><!-- Because this grid is bound to the control it self you will always use this property, unless you rename it :-) -->
</Grid>
Now the code behind of the UserControlWithBinding.xaml.cs:
/// <summary>
/// Interaction logic for UserControlWithBinding.xaml
/// </summary>
public partial class UserControlWithBinding : UserControl
{
public UserControlWithBinding()
{
InitializeComponent();
IAmGroot.DataContext = this;// this is where we set the data context for the grid so it uses the UserControl and not the inherited one. This will allow us to have the DataContext for User Control to be still inherited but the grid will look into a UserControl as an object to assign it to it's data context.
}
public string Status
{
get { return (string)GetValue(StatusProperty); }
set { SetValue(StatusProperty, value); }
}
// Using a DependencyProperty as the backing store for Status. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StatusProperty =
DependencyProperty.Register("Status", typeof(string), typeof(UserControlWithBinding), new PropertyMetadata(null));//note that I am using null and not string.Empty
}
Now let's use our control in xaml:
<local:UserControlWithBinding Status="{Binding PropertyThatYouWantToBindThisControlsText}"/>
This should solve your problem.

FocusedElement is not being honoured

I have created a basic application using Prism & MVVM. So far, it only consists of the Shell, and one View/ViewModel.
During application load, I am loading the View into my main region and this displays on screen. This works, but I cannot get the textbox on the view to focus. It looks like the cursor is in the box (although it's not flashing), but it doesn't accept text input until I click on the textbox.
I've recreated this in a new project, where all I've done is install prism/prism.unityextensions, set up the shell and the view, and loaded the view into the shell region. Neither xaml file has anything in the code behind.
Shell
<Window x:Class="MVVMFocusTest.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://www.codeplex.com/prism"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DockPanel LastChildFill="True">
<ContentControl Name="MainRegion" DockPanel.Dock="Top" prism:RegionManager.RegionName="MainRegion" />
</DockPanel>
</Grid>
</Window>
View1
<UserControl x:Class="MVVMFocusTest.View1"
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="300" d:DesignWidth="300">
<StackPanel>
<Grid FocusManager.FocusedElement="{Binding ElementName=Username}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0">Username</Label>
<TextBox Name="Username" Grid.Row="0" Grid.Column="1" ToolTip="Enter Username" TabIndex="0" />
<Label Grid.Row="1" Grid.Column="0">Password</Label>
<PasswordBox Grid.Row="1" Grid.Column="1" Name="LoginPassword" PasswordChar="*" ToolTip="Enter Password" TabIndex="1" />
</Grid>
</StackPanel>
</UserControl>
Can anyone point out what I'm doing wrong? As far as I'm aware, the FocusManager.FocusedElement="{Binding ElementName=Username}" should be sufficient to set the focus.
As per FocusManager documentation -
Logical focus pertains to the FocusManager.FocusedElement within a
specific focus scope.
So, its not necessary that element with logical focus will have keyboard focus as well but vice versa is true i.e. element with keyboard focus will surely have a logical focus as well.
As stated in documentation FocusManager.FocusedElement guarantees logical focus and not keyboard focus. So what you can do is create an attach behaviour similar to FocusManager.FocusedElement which will set keyboard focus on an element.
You can refer to this for setting keyboard focus using attached behaviour - Setting keyboard focus in WPF.
Code from that article -
namespace Invoices.Client.Wpf.Behaviors
{
using System.Windows;
using System.Windows.Input;
public static class KeyboardFocus
{
public static readonly DependencyProperty OnProperty;
public static void SetOn(UIElement element, FrameworkElement value)
{
element.SetValue(OnProperty, value);
}
public static FrameworkElement GetOn(UIElement element)
{
return (FrameworkElement)element.GetValue(OnProperty);
}
static KeyboardFocus()
{
OnProperty = DependencyProperty.RegisterAttached("On", typeof(FrameworkElement), typeof(KeyboardFocus), new PropertyMetadata(OnSetCallback));
}
private static void OnSetCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var frameworkElement = (FrameworkElement)dependencyObject;
var target = GetOn(frameworkElement);
if (target == null)
return;
frameworkElement.Loaded += (s, e) => Keyboard.Focus(target);
}
}
}
Use in XAML -
<UserControl xmlns:behaviors="clr-namespace:Invoices.Client.Wpf.Behaviors">
<Grid behaviors:KeyboardFocus.On="{Binding ElementName=TextBoxToFocus}">
<TextBox x:Name="TextBoxToFocus" />
</Grid>
</UserControl>
FocusManager.FocusedElement="{Binding ElementName=Username}" sets logical focus but not physical focus.
Physical focus is the normal focus, logical focus is kinda a second focus which is still a little bit buggy in wpf 4.0.
I would suggest you to use Keyboard.Focus(this.Username).

Dependency Property Binding in UserControl

My solution is implemented in MVVM. The view is a window which hosts a usercontrol. I have created a dependency property for this userControl as below :
public static DependencyProperty ListProperty = DependencyProperty.Register(
"ItemsList", typeof(List<RequiredClass>), typeof(UsercontrolTest));
public List<RequiredClass> ItemsList
{
get { return (List<RequiredClass>)GetValue(ListProperty); }
set
{
SetValue(ListProperty, value);
}
}
This property is bound to my viewmodel property (ListOfItems) in xaml :
<Window x:Class="TestProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Test="clr-namespace:TestProject"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Test:UserControlTest Grid.Row="0" ItemsList="{Binding Path=ListOfItems}" />
<Button Grid.Row="1" Content="AddItems" Click="Button_Click" />
</Grid>
</Window>
Also I have initialized the datacontext of the window in codebehind to the viewmodel. Problem is the binding never seems to happen and the set property is never called for the dependency property. Am I missing something here?
Those getters and setters are never called by the binding system (hence you should never place additional code there). The property is probably being set but unless you do something with it in the declaration of the UserControl nothing will be displayed. e.g.
<UserControl Name="control" ...>
<ItemsControl ItemsSource="{Binding ItemsList, ElementName=control}" />
</UserControl>

TwoWay Binding with UserControl

I am trying to set twoway binding on a UserControl that I have created.
When I use the control in Xaml is set the DataContext like so...
<uc:MyUserControl DataContext="{Binding Path=MyObject, Mode=TwoWay}" />
My user control is defined as the following....
<UserControl x:Class="SilverlightApplication1.XText"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBox x:Name="Text" Text="{Binding}"/>
</Grid>
</UserControl>
The data is displayed correctly, however if I make I change I wanted it to update with TwoWay binding.
I have tried this below, but it errors at runtime since no Path is defined.
<Grid x:Name="LayoutRoot" Background="White">
<TextBox x:Name="Text" Text="{Binding Mode=TwoWay}"/>
</Grid>
</UserControl>
Any ideas on how to get the control inside the usercontrol to twoway bind to the DataContext?
While your above (self-answered) answer seems to fix the problem, I can't help but think this is a problem domain issue. I have a hard time thinking why you'd want to bind directly like that in the first place, especially since it gives you less control over what happens with the data.
Take the following:
<UserControl
x:Class="SilverlightApplication1.XText"
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"
mc:Ignorable="d"
x:Name="UserControl"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBox x:Name="Text" Text="{Binding Path=Value, ElementName=UserControl, Mode=TwoWay}"/>
</Grid>
</UserControl>
Then in the codebehind:
public partial class XText
{
public static DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(string),
typeof(XText),
new FrameworkPropertyMetadata(null)
);
public string Value
{
get { return ((string)(base.GetValue(XText.ValueProperty))); }
set { base.SetValue(XText.ValueProperty, value); }
}
...
}
Then, when you're ready to use it:
<uc:XText Value="{Binding Path=MyObject, Mode=TwoWay}" />
Yes, it's more code, but it gives you much more control over what happens with Value inside of your UserControl, and makes working with this code much much simpler in the future.
Thoughts?
-Doug
EDIT: fixed a couple typos.
I have found a solution that doesn't require you to give a name to the base control.
When I defined a name for the base UserControl it was creating issues for me when I was adding multiple instances to my Grid, since they were defined as the same name.
This is a combination of my first answer and Doug's answer.
Note the UserControl lacks the name property and the TextBox has no Binding declared in the XAML
XAML
<UserControl
x:Class="SilverlightApplication1.XText"
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"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBox x:Name="MyText"/>
</Grid>
</UserControl>
CodeBehind
public partial class XText
{
public XText()
{
InitializeComponent();
MyText.SetBinding(TextBox.TextProperty, new Binding()
{
Source = this,
Path = new PropertyPath("Value"),
Mode = BindingMode.TwoWay
});
}
public static DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(string),
typeof(XText),
new PropertyMetadata(null)
);
public string Value
{
get { return ((string)(GetValue(ValueProperty))); }
set { SetValue(ValueProperty, value); }
}
...
}
When you are ready to use it do the following
<uc:XText Value="{Binding Path=MyObject, Mode=TwoWay}" />
Ok I think I have come up with a way to get this to work....
First I set a public property in my UserControl's code behind...
public Binding BindingValue
{
set { this.MyTextBox.SetBinding(TextBox.TextProperty, value); }
}
Then in XAML
<uc:MyUserControl BindingValue="{Binding Path=MyObject, Mode=TwoWay}" />

Categories

Resources