I have custom objects which implement INotifyProperyChanged and now I'm wondering if it is possible to implement soft delete which would play nicely with binding? Each object would have a IsDeleted property and if this property is set to true than it would not be displayed in GUI. I was thinking about making a custom markup extension which would decorate Binding class but it hadn't worked out as expected. Now I'm considering using MultiBinding with IsDeleted as one of bound properties so that converter would be able to figure out which object is deleted. But this solution sounds quite complicated and boring.
Does anybody have an idea how to implement soft deletes for binding?
You can bind the Property Visibility of the UIElement to the property IsDeleted of your object, to hide or show the elements.
As an example i use a TextBlock. In XAML you can write
<TextBlock Text="IsDeleted" Visibility={Binding IsDeleted}/>
NOTE: In the example above, the TextBlock is visible, when IsDeleted is true. I would define a positive property, such as Exists on the object. So you do not have to negate the boolean or to build your own converter.
WPF has a buildin converter that converts boolean to an enum value of Visibility.
Another way to implement soft deletes is by maintaining and exposing a collection containing only those items that haven't been deleted in your view model in addition to the collection of all items. This has the (to my mind) very great merit that it's not something your view needs to think about at all.
Related
i've got a textbox which text is binded to a listview selecteditem as follows:
<TextBox x:Name="txtAdditional" Width="300" Text="{Binding ElementName=lstPersons, Path=SelectedItem.Additional, Mode=OneWay}" />
Now i like to implement a mechanism to add new items to the listview using this textbox to get the actual data. So i would like to bind the text of the textbox to a property of the viewmodel so it can be processed by a command.
So it the textboxes text has to be binded to the listviews selecteditem and additionally to a property of my viewmodel.
I've searched around and found some approaches but i can't help to think that there should be some simpler mechanism to archive this goal.
What I found by now:
Using MultiBindung with some kind of ValueConverter? So it seems to me that this is primary for displaying and not for updating a viewmodels property.
The use of some selfdefined custom control?
The use of an BindingProxy with in- and out-dependencyproperties like in Impossible WPF Part 1: Binding Properties?
Is there another, simpler solution to this or would i have to use one of those above?
And if one should use one of those approaches, which one whould you choose?
I can't help but thinking that this issue hasn't been given some thoughts already, using an mvvm pattern?! ;-)
yes thanks to the hint from BionicCode.
We, or better I should have to think the MVVM concept out. Of course no - or at least as little code behind as possible.
I added the property "selectedPerson" to my viewmodel and bound the SelectedItem of the listview to this property. So the object related properties were at hand directly through the "selected" object in my viewmodel and there was no need anymore to access the textbox content at all.
Thanks to BionicCode for the hint!
I'm looking for a solution and/or the rationality behind why a Binding instance is shared within a DataTemplate. This ultimately comes down to the fact that within a DataTemplate, there's seemingly no way to force a new instance of a Binding on a DependencyProperty for each control generated. That is probably a fair and good assumption in all cases except when there are ValidationRules representing something specific about the instance of that control.
To elaborate (I can provide code, but I don't believe it's necessary), I use a DependencyPropertyDescriptor on IsEnabled to update one or more ValidationRules that belong to a TextBox.Text Binding, DatePicker.Text Binding, or a ComboBox.SelectedValue Binding, etc. The idea is that validation will be different or undesired when a control is not enabled.
Because of this, the ValidationRule's state of IsEnabled is specific to the individual control and because the ValidationRule Collection is a part of the Binding and the Binding instance is being shared - each control that ends up sharing that binding will update/override the previous IsEnabled value that was applied by the previously generated control's IsEnabled value.
IsEnabled is only one of at least two properties in the ValidationRule (another custom IsRequired DependencyProperty) that represent the state of the control to which the Binding is applied. When working outside of a DataTemplate (IE: The Binding instance is not shared), this works very well and ignores/alters the validation logic based on the state of the control. I'm not closed off to alternatives but do feel this has been (this issue aside) a very flexible and dynamic option that allows the Binding instance ValidationRule's and the control-changed state of the Rules to evolve effortlessly. This has also allowed me to avoid other obvious but much uglier options such as creating several Bindings, each representing one of the combinations of the ValidationRule's control properties and switching the whole binding out at the time the DependencyPropertyDescriptor fires. shivers
Any thoughts are MUCH appreciated!
I suggest you to use x:Shared attribute in the DataTemplate definition.
<DataTemplate x:Key="DataTemplateKey" DataType="{x:Type YourType}" x:Shared="False">
...
</DataTemplate>
Since you use it WPF will create a new DataTemplate instance on every request.
I have a WPF Data Grid bound to an observable collection, which is working as intended.
What I am trying to do now is add text below it to say: "Number of selected rows: {count goes here}"
What's the proper way to do this? I could add a new property in the View Model called SelectedCount or something similar and bind to that, but it doesn't feel right. It seems redundant. Also, I could set the label text dynamically in the code behind, but I'm not sure if that's the "right" place to do this either.
Here's an example below.
EDIT:
Please pretend there's a checkbox column header whose intention is to provide check/uncheck all functionality. The state of this header checkbox should not count towards the final count.
You could use element binding to declaratively bind to the SelectedItems.Count property in XAML:
<TextBlock Text="{Binding ElementName=MyDataGrid,
Path=SelectedItems.Count, StringFormat=Number of selected rows: {0}}" />
Update
Presumably you're using MVVM, so adding a SelectedXCount property to your view model is a perfectly reasonable application of the view model. The advantage of having it in the view model is that you could unit test based on the number of selected items. E.g. if you want to check that the user can only progress (a CanNext property returns true) if the user has selected some items.
The SelectedItems property is not a DependencyProperty so can't be bound to, but there are many articles online that get around the issue when using the DataGrid in MVVM. Most of the solutions involve using a mechanism for calling a view model command on the invocation of the DataGrid's SelectionChanged event.
I have a bit of a problem with my Silverlight application, and my usage of the MVVM pattern.
In my View I have a DataGrid. The ItemsSource would normaly be bound to the ViewModel, but in my specific case I need the columns to be dynamic and my items collection consists of a Dictionary for each item, so I have no class properties to show. My solution was to generate all this in codebehind, since the actual design of the DataGrid has nothing to do with my ViewModel. This was the only solution I could think of since the columns can't be databound.
I have got all of this to work. My problem is that I'm using RIA and the view has no idea when the items collection has finished loading. I tried my design out by putting an ordinary button on the view to trigger the codebehind function, but obviously this solution is no good. I need my codebehind function to run as soon as my item collection has finished loading.
Can I make my codebehind listen to the ViewModel?
I have a feeling that you are messing up things somewhere.
For your question I think you can solve it by having an event in the ViewModel.
Subscribe to that event in your view's view_Loaded event and call the codebehind function in the handler.
I would recommend you to recheck your design and to see if this is really necessary.
I understand what you mean, we once had to do the same thing generating random columns which is a PIA in silverlight because you would need some kind of object that has a dynamic set of properties.
I see you've found the Dictionary solution. What I would suggest, which isn't per sé the cleanest solution but it is cleaner then putting the stuff in the code behind, is to add this in a converter. Then bind the collection to the itemssource of an itemscontrol and then when the list propertychanged is raised you assemble the datagrid in the converter.
small example:
<ItemsControl Grid.Row="1" ItemsSource="{Binding theListOfEntities, Converter={StaticResource theconverter}}"/>
I have a UserControl that contains - among other things - a ListView. The ListView has a different data context than the UserControl (this data context is not exposed). If someone consumes my control, I would like them to be able to (indirectly) bind to the ListView's ItemsSource dependency property. It should really feel like the user is binding to a typical ItemsSource.
I'm not sure what the best way to proceed is. Looking at how ItemsControl's ItemsSource property worked in Reflector showed some logic that seemed a bit more involved than ought to be necessary for simple forwarding.
My current best idea is to expose a collection as a dependency property on the outer control and, when it is updated, update the ListView's ItemsSource. But I'm not sure what type this collection should be (should I require an ObservableCollection<T>, for example), or if there are any gotchas I should look out for.
Any suggestions or advice would be much appreciated.
Thanks.
Use AddOwner to add your UserControl as an owner of the ItemsControl.ItemsSourceProperty. In the new property meta data, give a property changed callback that sets the ItemsSource of your ListView.