WPF bind usercontrol's property to parent's property - wpf

I have created a usercontrol, which has 2 dependency properties. I want to bind those dependency properties to the mainViewModel's property, so that whenever something gets changed in the user-control the parent's property gets updated.
I tried, binding it normally but it didn't work. How can I bind the user-control's DP to the parent's property.
I tried this:
UC:
<TextBox Name="TextBox" Text="{Binding ElementName=UCName, Path=DP1, Mode=TwoWay}"/>
MainWindow:
<UCName:UCName Width="330" CredentialName="{Binding Path=DP1, Mode=TwoWay}"></UCName:UCName>
Thanks

For binding to the parent's properties you should use RelativeSource in your Binding. Like this:
<TextBox Name="TextBox" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UCName:UCName}}, Path=DP1, Mode=TwoWay}"/>
Details: RelativeSource Markup Extension
Note: Don't forget define namespace UCName.

Something like this:
<MainWindow DataContext="mainViewModel">
<local:TestControl ucDependProp="{Binding viewModelProp}/>
</MainWindow>
className: TestControl.xaml
<UserControl Name="thisControl">
<TextBox Text="{Binding ElementName=thisControl, Path=ucDependProp}/>
</UserControl>
The user control shouldn't be aware of the parent view model.

Related

Binding ToolTip in UserControl

I tried to bind a ToolTip text in a UserControl this way:
<Grid.ToolTip>
<TextBlock
Text="{
Binding Path=InfoTT,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}
}" />
</Grid.ToolTip>
And it doesn't work, the Tooltip was empty and in logs, I saw:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.UserControl', AncestorLevel='1''. BindingExpression:Path=InfoTT; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')*
But when I did:
<Grid
ToolTip="{
Binding Path=InfoTT,
RelativeSource={
RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}
}
}">
</Grid>
It worked. Can anyone explain why the first way doesn't work?
When Binding.RelativeSource doesn't resolve, you can always be sure that the Binding.Target is not part of the visual tree.
In your first example you are explicitly defining the tree structure of the ToolTip. You are explicitly creating the content e.g. by adding the TextBlock. The content of the ToolTip is not part of the visual tree and therefore the Binding.RelativeSource can't be resolved.
In your second example, you let the FrameworkElement implicitly create the ToolTip content.
Now FrameWorkElement will first resolve the Binding, which resolves, as the FrameworkElement is still part of the visual tree. The resolved value is taken, ToString invoked, a TextBlock created and the string value assigned to TextBlock.Text.
Solution
To solve the binding problem, when implementing the ToolTip explicitly, you can implement a Binding Proxy as suggested in a comment by #Mark Feldman which makes use of the StaticResource markup to provide a Binding.Source to elements that are not part of the visual tree.
It's basically a bindable ObjectDataProvider.
A similar solution to the binding proxy is to define the content as a resource of the Grid and then reference it via DynamicResource using a ContentPresnter:
<UserControl>
<Grid>
<Grid.Resources>
<!-- The proxy -->
<TextBlock x:Key="ToolTipText"
Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=InfoTT}" />
<Grid.ToolTip>
<ToolTip>
<ContentPresenter Content="{DynamicResource ToolTipText}" />
</ToolTip>
</Grid.ToolTip>
</Grid>
</UserControl>
But you could also make use of the fact that the DataContext is still inherited. Bindings to the DataContext will still resolve.
In your scenario, where you want to bind the content of the ToolTip to a property of the parent UserControl, you could bind this property to a property of the view model, which is the current DataContext of Grid (and therefore for its ToolTip). I only recommend this, when binding to business data and not layout data:
<UserControl InfoTT="{Binding ViewModelInfoTT}">
<UserControl.DataContext>
<ViewModel />
</UserControl.DataContext>
<Grid>
<Grid.ToolTip>
<ToolTip>
<TextBlock Text="{Binding ViewModelInfoTT}" />
</ToolTip>
</Grid.ToolTip>
</Grid>
</UserControl>
If you don't use view models and host the data directly in the control, you may like to set the DataContext to the control itself. This way you simplify all bindings and of course can now bind to the UserControl from within the ToolTip:
// Constructor
public MyUserControl()
{
InitializeComponent();
// Set the UserControl's DataContext to the control itself
this.DataContext = this;
}
<UserControl>
<Grid>
<Grid.ToolTip>
<ToolTip>
<TextBlock Text="{Binding InfoTT}" />
</ToolTip>
</Grid.ToolTip>
</Grid>
</UserControl>
Alternatively override the DataContext. Of course you'll lose access to the current context:
<UserControl>
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestoType=UserControl}>
<Grid.ToolTip>
<ToolTip>
<TextBlock Text="{Binding InfoTT}" />
</ToolTip>
</Grid.ToolTip>
</Grid>
</UserControl>

Change DataContext of specific property inside control - WPF

I have User control which contains TextBox with WaterMark inside
<AdornerDecorator>
<TextBox
Height="20"
Margin="10,0"
Grid.Column="0"
Text="{Binding MainCategoryTextBoxValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Name="MainCatTextBox">
<controls:WatermarkService.Watermark>
<TextBlock VerticalAlignment="Center" x:Name="MainCategoryTextBlock"> </TextBlock>
</controls:WatermarkService.Watermark>
</TextBox>
</AdornerDecorator>
You can see here WatermarkService implementation
https://stackoverflow.com/a/836463/1548347
I want take "MainCategoryTextBlock" textblock inside <controls:WatermarkService.Watermark> and set it DataContext to be same like my UserControl DataContext in order to change Watermark text in RunTime from my ViewModel.
I tried to bind "MainCategoryTextBlock" DataContext with RelativeSource to my UserControl DataContext but I didn`t succeed (maybe syntax error - Im not sure).
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
Do you have any clue how can I solve it?
Thanks
If your UserControl has a name then you can do it like this:
DataContext={Binding ElementName="YourUserControlName", Path=DataContext}
But i can see that you are using your textbox inside an adorner decorator so you can't use FindAncestor in this case because your textbox and your UserControl won't belong to the same visual tree.
You should be setting the data context property of your window to your view model, and bind the text property of your textblock to your view model property.
<TextBlock Text={Binding Path=PropertyOnViewModel} />

what is the difference between {binding} and {binding Account}?

here , i am confuse on {binding} and {binding Account}.when to use only simple {binding} and binding with proprty name in below code binding occur as :Content="{Binding}"
<Border Grid.Row="1" Grid.Column="0"
Style="{StaticResource MainBorderStyle}"
Background="{StaticResource ResourceListGradientBrush}"
BorderThickness="0,0,1,1"
Padding="0">
<StackPanel>
<HeaderedContentControl
Content="{Binding}"
ContentTemplate="{StaticResource CommandsTemplate}"/>
</StackPanel>
</Border>
where is below code binding occur
as
Text="{Binding Path=Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/>
so i want to know use of them and difference of them.thank in advance.
{Binding} will simply bind to the actual object set in the DataContext. {Binding Account} will bind to the Property Account on that object.
In your case if you had a ViewModel set against the root level DataContext then Account would be a property called Account on the ViewModel
Where you have
<HeaderedContentControl
Content="{Binding}"
ContentTemplate="{StaticResource CommandsTemplate}"/>
All this is doing is setting the Content of the HeaderedContentControl to the ViewModel provided you have something like this in the code behind of the Window or UserControl
DataContext = yourViewModel;
{Binding} will bind to the current DataContext
{Binding Account} will bind to an Account property on the current DataContext

WPF Bind to ViewModel of another element

Just an example. The CustomControl has a ViewModel with a property called "Test"
How could I bind the textbox to that specific property?
Can you access the siblings ViewModel?
<TextBox Text="{Binding ElementName=myControl, Path=ViewModel.Test}"></TextBox>
<Controls:CustomControl x:Name="myControl" />
Siblings ViewModel would be in its DataContext try
<TextBox Text="{Binding ElementName=myControl, Path=DataContext.Test}"></TextBox>
<Controls:CustomControl x:Name="myControl" />
May be this is what you required-
<TextBox Text="{Binding Source={x:Static local:VieModel}, Path=Test}"></TextBox>
<Controls:CustomControl x:Name="myControl" />
Don't forgot to add the markup extension to include the namespace where your class Viewmodel exists - xmlns:local="clr-namespace:ViewModel NameSpace"

Binding parent container props to content child control in Silverlight

Example:
<UserControl x:Name="userControl"
<StackPanel x:Name="container" Margin="0">
<TextBox Text="{Binding Path=SettingValue, RelativeSource={RelativeSource Mode=Self}}"/>
</StackPanel>
</UserControl>
UserControl contains SettingValue dependency property, TextBox doesn't,
so this example won't work.
I could've done this if I had AncestorType, like in WPF:
RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControlType}
Is there any possibility to bind to UserControl.SettingValue property?
Did you try the following? Use the ElementName source (the syntax might be a bit off).
<TextBox Text="{Binding Path=SettingValue, ElementName=userControl"/>
The answer I've found here:
Binding Silverlight UserControl custom properties to its' elements

Resources