Selected item in listview diffrent approaches - xamarin.forms

I have a question. Two approaches below correctly bind selected item for listview. Approach 1 seems to be much simpler and quicker, Approach 2 seems to be more code consuming. Is there anything else that's makes difference between those two approaches or this is doing exactly the same? My only concern is whether Approach 2 works in TwoWay mode by default and can it be changed to another mode?
Thanks for the info.
Approach 1:
<ListView SelectedItem="{Binding SelectedOrder, Mode=TwoWay}" ItemsSource="{Binding Orders}">
..
</ListView>
Approach 2:
<ListView ItemsSource="{Binding Orders}" ItemSelected="OnPlaylistSelected">
..
</ListView>
This also requires this in code behind of course:
void OnPlaylistSelected(object sender, SelectedItemChangedEventArgs e)
{
_viewModel.SelectOrderCommand.Execute(e.SelectedItem);
}

Having had a quick look at the docs, I cannot find a definitive answer myself:
ListView Interactivity
If I were to hazard a guess though, I would suggest that if you are just wanting to assign something to SelectedItem and do nothing fancy, then Approach 1 is the way to go.
If however you wanted to do other things other than just set the SelectedItem, then you would go with Approach 2 as it will give you a bit more control over what is happening in the background.

Is there anything else that's makes difference between those two approaches or this is doing exactly the same?
The Approach 1 uses the TwoWay binding model, and the Approach 2 uses the Default binding model. But here the default model should also be TwoWay. Therefore, they should be the same.
Generally you don't need to go looking. Most of the controls behave as you would intuitively expect them to.
For example:
An Entry is two way by default because that's just what you would expect.
A Label is one way because... well... you can't set a label through the UI.
And so on.
The only time you really need to set binding mode explicitly is when you are deliberatly doing something out of the ordinary, like you want to use an Entry because you like the look but don't want the user to be able to enter a new value: That's a weird use-case for an entry so you probably need to explicitly set its binding mode.
And from the definition of BindingMode Enum, if using BindableProperty to bind, the default value should be OneWay.
Default : When used in Bindings, indicates that the Binding should use the DefaultBindingMode. When used in BindableProperty declaration, defaults to BindingMode.OneWay.
If you want to modify the binding model on runtime, you could use code to do that,
listview.SetBinding<StoreDetailViewModel>(ListView.ItemsSourceProperty, vm =>vm.items,mode: BindingMode.TwoWay);

Related

Populate comboboxes INSIDE a datagrid with UNIQUE data IN actionscript (flex)

i've searched for several hours, and didn't find an answer for my problem.
i'm trying to place comboboxes in a datagrid filled with DYNAMIC data. (the number and the content of these comboboxes always change. i don't know in advance how many columns there are, where i need to use comboboxes. so every single combobox gets a unique dataprovider, which comes from an external source, WHEN the program runs.)
-i found MANY threads discussing this problem, but solving via crappy mxml files, filling the comboboxes inside the sourcecode by hand. i want to point out, that isn't good for me.
-i found a better solution, in which they used some sort of custom itemrenderer to get the data from the internet. (kind of a country chooser thing) but sadly that wasn't good enough, because the number and name of the countries in the world are static more or less, they don't change. so their renderer class didn't depend on any parameters from the main algorithm.
but in my program i calculate the data in my own actionscript objects, then fill an arraylist with that. so at the beginning i load the desired data from the net, and when i get the response of the urlrequest, AFTER that i start to populate the datagrid/combobox.
i can fill any datagrid or combobox without trouble, but to put that combobox inside a datagrid cell seems to be impossible.
could anyone please help? it drives me crazy. i managed to do this in several languages before, c#, java, even php+html, but in flex it looks way too complicated then it should be.
EDIT:
i'm aware, that this amount of network activity could mean some load on the server. i didn't design the philosophy behind it, i just need to wrote a client which meets the expectations. my program looks something like this:
(i'm willing to rewrite any part of it, just to make those nasty comboboxes work)
=========
main.mxml file
this is the main program, i handle some login related stuff here, and set basic design properties for the datagrids. (for example: maxwidth, maxheight, layout constraints etc.)
nothing interesting, except the command when i instantiate the actionscript class, which i wrote to fill the datagrid.
"..<fx:Script>
<![CDATA[
private var myGrid1:MyGridType;
..
somefunction {
myGrid1 = new MyGridType(theDatagridDefinedBefore, "argumentNeededToFillDataGridsWithUniqueData");
}
]]>
</fx:Script>.."
=========
MyGridType.as file
in the constructor i call a urlrequest with the help of the second argument, then add an eventlistener to it. when the data arrives, the eventlistener fires the filler function: i read the results into an arraycollection, then make it the dataprovider for the the datagrid in the first argument.
so far so good.
here comes the trouble with the comboboxes. for a specific number columns, i instantiate my combobox class. let's call that class "MyComboBoxType".
"..
blablabla = new MyComboBoxType(theDatagridDefinedBefore, param1, param2, param3);"
=========
MyComboBoxType.as file
i do nearly exactly the same, what i did in the MyGridType class. call for help from the net with param1-2-3. when i receive the data, fill an arraycollection. maybe set that arraycollection to be the dataprovider for a combobox. AAAAAAAND now i want that arraycollection or combobox to be on the datagrid "theDatagridDefinedBefore".
I know it's not exactly what you're trying to accomplish, but I had a somewhat similar issue in the past. Take a look at How to get the value of a ComboBox within a DataGrid to see if it helps.
If it were me, I would populate the entire ArrayCollection set before binding them to the datagrid if at all possible.
You should build up your custom [Bindable] data structure - say MyGridData class - for the rows in the grid (if you haven't done it yet);
the dataProvider of your grid should
be an Array / ArrayCollection /..
of MyGridData objects.
this step clearly works already, but
for the integrity: override the
getItemEditor function, or specify
it explicitly using mxml, to return
the combobox when needed.
as for the dataProvider of the
combobox, you should specify the
data.comboArray from inside the
renderer class, where data is the
MyGridData instance used by the row
you are processing. (overriding the
set data(value: Object):void
function, you can pre-process it.)
this way, you are working with the
reference of your original instances,
and by the binding you can detect /
show any changes to them directly.

Is it possible to have WPF/SL4 perform operations on a property binded to another control?

Using SilverLight, one can bind the value of a control to a property from a datacontext. That's fine.
It is possible to use StringFormat along with the binding declaration to format the value. Again, that's cool!
However, I can't find a way to have the binding with some operation done to it before it gets displayed. I know I can code an IConverter but I was looking for something purely in XAML if that exists. I could also add a property to the class that returns the data in the correct way, but still what would happen if you don't have the source of the class?
For example, let's say I have this class for my datacontext (properly setup with notification and the like):
public class Info
{
public int SomeValue {...} // Value from 0 to 15
}
I would like to have a binding that would display 45 instead of 15 where the binding would be declared something like {Binding SomeValue, Operation="*3"}
Is there something like this in the .NET world (either from MSoft or OpenSource)?
found the link I was talking about.
Still, Charles Petzold also suggest to rather use a ValueConverter, even though some arithmetics is possible in pure XAML

DataGrid crash on CompositeCollection Edit

I have a DataGrid.
It's ItemsSource is bound to the ModelView's CompositeCollection through the ViewModel.
The CompositeCollection consists of 2 ObservableCollections.
The display on the grid is fine. I am able to see the collection.
However, when I try to edit one of the rows, I get a crash (NotSupportedException) of:
"'EditItem' is not allowed for this view"
How do I make the rows editable? I need to be able to edit the ModelViews representing each row in the Grid.
Here is the CompositeCollection Property code that I use to bind to the itemssource:
this isn't the exact code since I am not allowed to post the exact code but it is the same logic on how I make the collection
public CompositeCollection ModelViewsCollection
{
get
{
CollectionContainer modelViewContainer;
CompositeCollection modelViewCollection = new CompositeCollection();
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection;
modelViewCollection .Add(modelViewContainer);
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection2;
modelViewCollection .Add(modelViewContainer);
return modelViewCollection;
}
}
CompositeCollection does not implement IEditableCollectionView which is used by the datagrid to edit.
I have had the same issues, and ended up doing my own fake composite collection on the view model, similiar to what you have, if all you are putting in your collection is two observable collections, its not to hard to track the changes listening to collection changed on both of them. and make your viewmodels collection consist of both of them
You could even do the dirty hack that i did, of rebuilding the ObservableCollection that the grid binds to every time one of the collections change (not elegant i know, but ill go back and optimise when i get time.. i.e. never) With a linq query this stuff is really easy.
Otherwise maybe you could derive from CompositeCollection and try and add the IEditableCollectionView, if you get that working be sure to let me know.
here is the same question on the datagrid forum

ASP.Net: Is it possible to skip databinding of an element if an error occurs?

I use a lot of repeaters for different elements of our sites, and I've always wondered if there was a way to have the repeater skip an element if an exception occurs instead of having the whole page crash?
In particular, I've inherited a system from another developer that using a similar design, however he didn't include any kind of validation for his business objects, and it a single property is missing, the whole thing goes up in smoke.
Any suggestions?
Thanks in advance!
The simplest suggestion I can offer is the check the validity of the data before it's passed to the repeater. I don't believe there's any way to get the stock repeater to skip a data element on error.
The other approach is to build your own repeater, inheriting from the base Repeater, to add that functionality but I've no sample code to offer. Perhaps someone else may be able to help there.
The way I see it, you have at least three options.
You could create a custom repeater control that inherits System.Web.UI.WebControls.Repeater and override the databinding behaviour to be more try-catchy (probably fail silently on databinding errors). You couldd then easily replace all instances of the standard Repeater with this new one.
You could filter your datasources before databinding to remove items you know are going to cause problems beforehand. This option may be quite laborious and something of an iterative process.
You could try adding default values to the business objects, so that the properties you're binding to return a default instance rather than null (not nice either).
That's my thoughts anyway.
One question - you say "when a property is missing". Do you mean he's using a style of databinding syntax that offers no compile-time checking and is referencing properties that don't exist, or is referecing properties that are null?
Edit
OK, so you're referencing properties that are null. If you have access to the code for the business objects you could modify them so they return a new, non-null instance (this is the third option I gave).
You don't say if you're using .net 3.5, but I'll assume you are. You could add a new property "IsValidForDataBinding" on to each of your business objects. In the getter logic you could check each of the necessary properties and sub-objects to check for validity, non-nullness etc and return a bool. When you come to bind your repeater, write a simple linq statement that filters-out the invalid items (i.e. where IsValidForDataBinding = false). Having said that, I still think that writing a derived repeater control could be your easiest option.
Have you tried using string.isnullorempty("the string") to check for a value before referencing the property?
Here's a reference: MSDN

ContextMenu Binding Source within a DataGrid using MVVM

I've got a datagrid column as below:
<toolkit:DataGridTemplateColumn>
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=LabelName}" Background="{Binding Path=Color}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem x:Name="Assign" Header="Assign"
mvvm:CommandBehavior.Event="Click"
mvvm:CommandBehavior.Command="{Binding Path=DataContext.EditLabelCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}, AncestorLevel='1'}}"
mvvm:CommandBehavior.CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
I'm trying to get to the DataContext's EditLabelCommand, but I cannot find the binding source. What should I do to access my DataContext's commands?
DataContext changes as you move down the visual tree when you either a) bind DataContext to something else, or b) use something like an items control (or in your case a grid), which repeats your data template once per item in a collection, setting the data context for each item.
In your example, your menu item has the same DataContext as your TextBlock. This will be the object bound to each row of your data grid.
Based on your code, I think you have one EditLabelCommand available in the DataContext set for your entire UserControl. This is likely the parent of the collection you are binding to the grid. (Please correct me if any of these assumptions are wrong.)
If this is the case, there are several things you can do:
You can continue to use relative binding. This is complex and error
prone, as you have seen, and does not lead to good reuse of your data
templates or other XAML. I recommend you avoid this technique.
A simpler way to keep the command in the overall datacontext is to use
a CommandReference from the WPF Model-View-ViewModel Toolkit. This
allows you to reference the command as a resource and use resource binding to
access it. Like this:
<UserControl.Resources>
<mvvmToolkit:CommandReference x:Key="EditLabelCommandReference" Command="{Binding EditLabelCommand}" />
</UserControl.Resources>
<!-- Your command binding then looks much simpler -->
mvvm:CommandBehavior.Command="{StaticResource EditLabelCommandReference}"
Another (probably better) technique is to refactor to use the MVVM pattern for each row. This way, you would use a simple ViewModel per row of your grid. This allows each row to maintain its own state. Because you can move the Command implementation into this ViewModel, you have a command per row and no need to pass an argument. This makes it possible to edit more than one row's label at a time. (If this a requirement.)

Resources