Silverlight telerik gridview force binding refresh with MVVM - silverlight

This is the scenario:
I have a telerik gridview on my page, this is bound to a PagedCollectionView
with items of class "GekoppeldeOntvangstRegel",
this class implements INotifyPropertyChanged
Several columns have a CellTemplate with a TextBlock bound to an object of this class, like this:
<TextBlock Text="{Binding ConverterParameter='aantal', Converter={StaticResource GekoppeldeRegelDecimalFormatConverter}, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True}" HorizontalAlignment="Right" ToolTipService.ToolTip="{Binding ConverterParameter='aantal', Converter={StaticResource GekoppeldeRegelToolTipDecimalFormatConverter}}" />
This converter converts the "Aantal" property to a string with a specific number of decimals.
When I update the "Aantal" property from code with the OnPropertyChanged("Aantal") of course the binding isn't updated (since the textblock is bound to the entire object, not the property) so the old value is still visible.
How can I refresh the column contents from my viewmodel or object when the property changes?
When I bind directly to the "Aantal" property everything works perfectly (besides the converter not being applied, which is necessary)

As a workaround I now have created several extra properties on the "GekoppeldeOntvangstRegel" class.
These properties call the converter and return the right value with the right number of decimals.
On these properties raising OnPropertyChanged does work to refresh the bindings.
I'm not really happy with this solution but it works for now.

Related

Binding UI-element to UI-element like Textbox to Textbox

I have UI-elements like a textbox and I want to bind them to a ViewModel. I need to access many properties of the textbox like the text- or the IsEnabled-property.
Is it possible that I bind the textbox directly to another textbox in the ViewModel with all their properties instead of binding every single property to properties?
Yes, using an ElementName, but you still bind all properties though.
<!-- Bound to ViewModel -->
<TextBox Name="tbOne" IsEnabled="{Binding OneIsEnabled}" Text={Binding TextOne}/>
<TextBox Name="tbTwo" IsEnabled="{Binding ElementName=tbOne, Path=IsEnabled}" Text={Binding ElementName=tbOne, Path=Text}/>
There is no built-in way to bind all dependency properties of the TextBox to another. Personally, I would prefer binding directly to the ViewModel.
An alternative solution would be to create a UserControl that internally clones the TextBox with all bindings:
<CloneControl Target="{Binding ElementName=tbOne}"/>
Here, the ControlControl would inspect the target, and have code that create a new TextBox, and sets the bindings in code. This is only useful if you are doing this very often, and there is a slightly performance price to pay, as you are adding another level of controls to the UI tree.

wpf source and target binding in two different path

How can I bind a Text property for my TextBox that read from a source but it will store its value to a different target?
Let's say
I have a textbox which is bond to a path in a CollectionViewSource
<Window>
<Window.Resources>
<CollectionViewSource Source="{Binding Source={StaticResource ProgramView}, Path='FK_LevelList_ProgramList'}" x:Key="LevelLookupView" />
</Window.Resources>
<TextBox Name="FeePerTermTextbox" Text="{Binding Source={StaticResource LevelLookupView}, Path='FeePerTerm', Mode=OneWay, StringFormat=c2}"/>
</Window>
When perform save, the value of the TextBox will store to another model that is different from the CollectionViewSource
Thanks
I consider this flawed. What happens if the source gets updated? Should the textbox be overwritten?
The reason for this design is imho, that the UI should reflect the "traits" of the element set as DataContext, therefore i expect it to contain the value i give in the model or in the ui. Now there is of course nothing stopping you from not writing the value in your viewmodel to your model, when receiving the set value from the textbox.
public class Redirecter
{
public string FileName
{
get{return mModel.FileName;}
set{mProxy.FileName = value;}
}
}
But this of course won't work well together with INotifyPropertyChanged. I would use a different approach. Use a model that reflects your ui more. If you open the view fill in this ui model with your settings from model A. If you now save this, save each property into Model B.

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}" />

Combobox's SelectedValue (or SelectedItem) OneWay binding not working. Any ideas?

In the below window, the Existing Reports combo is bound to an observeablecollection of reportObjects. I have a reportObject property currentReport bound to the combo's SelectedValue property, OneWay. However, that's not working when bound in XAML.
SelectedValue="{Binding currentReport, Mode=OneWay}"
TwoWay binds fine, but I can't do it that way without writing an undo() method to the reportObject class. I'm binding the currentReport's properties to the various textboxes for editing. I want to bind OneWay so the source doesn't get changed. The currentReport's properties are all TwoWay bound to the corresponding textboxes so when I update the table in SQL [Save], it'll pull from that object, who's data is current.
<TextBox Text="{Binding currentReport.reportName, Mode=TwoWay}"
All of the properties bound from currentReport to the textboxes work fine as well. The only problem is the OneWay binding from the SelectedValue to the currentReport object. Does anyone have any ideas how to get this to work? I saw there was a bug, but the post I saw was 2009.
Sorry about the yellow. Not my idea. =)
EDIT: Added this XAML just in case.
<ComboBox ItemsSource="{Binding reportsCollection}" SelectionChanged="cboReports_SelectionChanged"
DisplayMemberPath="displayName"
SelectedValue="{Binding currentReport, Mode=TwoWay}"
x:Name="cboReports" Width="342" Height="40" VerticalAlignment="Center"/>
Forget about you need to change values - that is a separate problem - need to review your data design. Start with the UI problem question. If you want a user to be able to select an item from a combo box then it must have two way binding. Your first question is SelectedValue="{Binding currentReport, Mode=OneWay}" is failing why?

WPF databinding and converters

I'm trying to databind to a listbox like so:
<ListBox x:Name="MyListBox" Margin="0,0,0,65">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource MyConverter}}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The reason I am binding to the whole object and not a property is because my converter will need multiple properties of the object to build the string that it returns.
This works and my string is returned. But then when I change the ObservableCollection that this is based on the value doesn't change on the screen. If I bind to just a single property and change it, then the value does change.
What can I do differently? I can't bind to a single property since I need the entire object in the converter... And the ConverterParameter is already being used.
Remember, if you bind to the "main" property and the value of the main property itself isn't changed, the binding will have no reason to refresh itself. It has no clue that your converter is actually based off of a sub-property. What you can do is use a MultiBinding where you bind not only the "main" property, but also a specific sub-property. This gives your IMultiValueConverter implementation access to the main data object, but because you're also binding to the sub-property that's changing, will also be refreshed when that sub-property's value changes.
You can try using a MultiBinding which I believe updates whenever any of its Bindings are triggered. You can also use an IMultiValueConverter or just take advantage of the StringFormat of the binding.

Resources