Bind value between control in different view -- WPF / MVVM - wpf

in my MVVM application (in wpf)
i have two view and I want to bind the context of my label on my textbox value (in the other view)
SelectorView.xaml contain this control:
<TextBox x:Name="tbArt" value="XX"/>
DescriptionView.xaml contain this control:
<label context="{binding on the tbArt value????}">
Is that possible directly without going in code behing and viewmodels ?
Will the label be refresh automatically ?
Thanks !

If both of the controls databinds to the same property the label will refresh when the value is changed.Make sure that the property triggers property changed when it gets changed.
ex:
in XAML.
<TextBox x:Name="tbArt" value="{Binding Path=TheProperty, UpdateSourceTrigger=PropertyChanged}"/>
<label context="{binding TheProperty}">
in the textbox make sure you use:
UpdateSourceTrigger=PropertyChanged
. otherwise the property won't be changed until focus is shifted from the textbox.

If all you want to do is display the value of one control in another control within the same window/page, you could do the following:
<TextBox x:Name="tbArt" Text="XX" />
<Label Content="{Binding Path=Text", ElementName=tbArt}" />
This will bind the content of the Text of the label to a control with the name "tbArt". You can do the same thing with other properties of the control as well.
For instance,
<TextBox x:Name="tbArt" Text="XX" Width=33 />
<Label Content="{Binding Path=Width, ElementName=tbArt}" />
will display "XX" in the textbox and "33" in the label.

Related

Expander-like WPF control that only hides empty children

In my WPF view, I need something similar to an Expander or a TreeView, but instead of completely hiding the content, I only want to hide empty parts, i.e. TextBoxes with null or empty text, or empty ItemCollections.
I thought about using a style with a DataTrigger or set Visibility with a converter, but how would I link that to the parent's setting (e.g. IsExpanded)?
I would like to avoid doing this in the ViewModel, as that would need a property for each section (and I need lots of them), but it's purely visual and therefore IMHO it only belongs to the View.
So I guess the way to go is to use DependencyProperties or write some CustomControls, but I don't have an idea where to start. The XAML of the end result could look something like this:
<CustomExpander Header="Main" CollapseContentIfEmpty="True">
<CustomExpander Header="Section1" CollapseContentIfEmpty="True">
<StackPanel>
<TextBox Text="{Binding SomeString}" />
<TextBox Text="{Binding SomeEmptyString}" />
</StackPanel>
</CustomExpander>
<CustomExpander Header="Section2" CollapseContentIfEmpty="True">
<ListView ItemsSource="{Binding SomeCollectionView}" />
</CustomExpander>
</CustomExpander>
In this example, if CollapseContentIfEmpty is set to true and the CollectionView shows no elements (e.g. due to filters), only the content of SomeString should be visible, along with all the headers. If SomeString is empty, only "Main" should be visible, as now all child CustomExpanders are empty as well.
Setting CollapseContentIfEmpty to false (e.g. via a Button like in Expander) would show all Children again, regardless if they are empty or not.
I thought about using a style with a DataTrigger or set Visibility with a converter, but how would I link that to the parent's setting (e.g. IsExpanded)?
Use a binding with a {RelativeSource}.
In the following example, the TextBlock is invisible unless you set the Tag property of the parent UserControl to true:
<UserControl xmlns:sys="clr-namespace:System;assembly=mscorlib">
<UserControl.Tag>
<sys:Boolean>false</sys:Boolean>
</UserControl.Tag>
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<StackPanel>
<TextBlock Text="text..."
Visibility="{Binding Tag,
RelativeSource={RelativeSource AncestorType=UserControl},
Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</UserControl>
You can of course replace the UserControl with a custom control with a custom bool property.
An Expander collapses its entire Content which is different from hiding specific controls in that content.

How to update an object's inner property from UI to VM? (WPF MVVM)

I have a property in my ViewModel, I'll call it "Project" which contains several nested lists inside of it. None of such lists has an associated property in the view model since I can show everything in xaml by using triggers and bindings.
My xaml shows the Project hierarchy in a treeview and its details in several views (a content control selects the right view depending on which item is selected on the treeview). One of those "details" is a property for the objects contained in one of the nested lists, I'm showing it in a textbox so the user can edit it, the problem I'm having is I don't see that property updated in the Project property in the VM once I make changes to it in the textbox.
I was told I have to create a property in the VM for that specific object's property I'm trying to edit, I just don't know how since the object is deep inside one of the nested lists of my Project object.
Common mistakes are:
Using OneWay binding mode instead of TwoWay
In XAML:
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" />
Not realizing that the update is not propagated to the VM until after the TextBox lost focus.
this is the default for the TextBox:
<TextBox Text="{Binding Path=Name, UpdateSourceTrigger=LostFocus}" />
You could change it to:
<TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" />

TextBox to TextBox on the fly data binding

There are two TextBox on the WPF page. While user is typing into the first TextBox, the second TextBox must display modified text from the first TextBox. As a result both values must be binded to a view model.
Can it be done with Data Binding?
I was able to get the second TextBox display text from the first one implementing DependencyProperty on my view model. But I don't have the slightest idea how to apply transformation on the fly.
Maybe there is an easy way to achieve this?
Just use databinding with UpdateSourceTrigger set to PropertyChanged:
<TextBox x:Name='txt1' Text="{Binding MyText, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name='txt2' Text="{Binding MyText, UpdateSourceTrigger=PropertyChanged}" />
In this case it will update ViewModel's property on the fly instead of waiting for FocusLost.

Prevent writing a lot of duplicate code in XAML

I have XAML:
<TextBlock Text="Param 1 name" Margin="6,6,0,0"></TextBlock>
<TextBox Text="{Binding Param1Value, UpdateSourceTrigger=PropertyChanged}" Margin="6,6,0,0"></TextBox>
<TextBlock Text="Param 2 name" Margin="6,6,0,0"></TextBlock>
<TextBox Text="{Binding Param2Value, UpdateSourceTrigger=PropertyChanged}" Margin="6,6,0,0"></TextBox>
...
<TextBlock Text="Param N name" Margin="6,6,0,0"></TextBlock>
<TextBox Text="{Binding ParamNValue, UpdateSourceTrigger=PropertyChanged}" Margin="6,6,0,0"></TextBox>
How can be optimized this code to prevent copy-paste?
Control, Style, ContentControl or DataTemplate?
I can use Style to reuse margin, but how can be reused structure of this pairs TexBlock and TextBox?
Make a UserControl with two properties (E.g., Caption and Text) and bind the TextBlock to the Caption and the TextBox to the Text property.
You could also use a Templated Control if you want to allow the designer to create a custom templates so he can fully control the UI design.
UserControl vs. Custom/Templated Control (read the entire thread for maximum benefit):
Well the difference between user control and custom control is that If
you have a portion of views or UI which will be used repeatedly in
your own project, using UserControl is a much simpler and preferred
way, but if you have a portion of UI and functionality which you
believe will be used aross different projects, then using custom
control is the right approach.
May be you should try an ItemsControl Class and set it's DataTemplate.

WPF: AutoCompleteBox SelectedItem

I have an object bound to controls in a window. There's a property on this object called "Region", and an ObjectDataProvider which is populated with a list of available "Regions". I'm using a WPF toolkit AutoCompleteBox to select the region selected but the value selected isn't update to reflect the region of the object. Eg: If I use the code below, I can open/save the form and the AutoCompleteBox appears blank, even though the region is saved (so it must be bound, but invisible?)
<input:AutoCompleteBox x:Name="txtRegionAuto" Grid.Row="0" Grid.Column="1"
IsTextCompletionEnabled="False" ValueMemberPath="Region" ItemTemplate="{StaticResource RegionDataTemplate}" Margin="2,4" Style="{StaticResource AutoCompleteComboBoxStyle}" TabIndex="8" SelectedItem="{Binding Region,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="lstRegion_SelectionChanged"
ItemsSource="{Binding Source={StaticResource regionProvider}}" MinimumPopulateDelay="400" />
The only way I can get the region to display in the box is with:
txtRegionAuto.SelectedItem = regions.FirstOrDefault(c => c.RegionID == region.RegionID);
But then when I come to save the form, the Region property on my object is null. I'm sure it's just a case of setting the right value binding, but I'm not sure what to use.
i guess you encountered a bug: https://connect.microsoft.com/VisualStudio/feedback/details/595640/autocompletebox-does-not-update-visible-text

Resources