Issue binding command parameter in Silverlight - windows-phone-7

I can't seem to get this to work right. Basically, I have an ObservableCollection that is bound to a list. Inside this collection, I have an object that I need to use to pass as a variable to a Command when it's executed. My plan was to pass this as CommandParameter, but I can't get it to work. The object is actually an Enum value, but I can't get it to work with anything but static text. Below is the code, it's using a MVVM concept using Interactivity(wi)and blend's dll(sl). The property is public on the ListItem, and does implement INotifyPropertyChanged.
Thanks.
<ListBox ItemsSource="{Binding Path=MyList}" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<wi:Interaction.Triggers>
<wi:EventTrigger EventName="SelectionChanged">
<sl:InvokeDataCommand CommandParameter="{Binding MyList.ListItem.Property}" Command="{Binding Source={StaticResource Locator}, Path=MyTestPage.TestExecute}" />
</wi:EventTrigger>
</wi:Interaction.Triggers>
...

<ListBox x:Name="listBox" ItemsSource="{Binding Path=MyList}" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<wi:Interaction.Triggers>
<wi:EventTrigger EventName="SelectionChanged">
<sl:InvokeDataCommand CommandParameter="{Binding ElementName=listBox, Path=SelectedItem.Property}" Command="{Binding Source={StaticResource Locator}, Path=MyTestPage.TestExecute}" />
</wi:EventTrigger>
</wi:Interaction.Triggers>
How about doing this? You want to bind to the selectedItem, not ?
MyList is your ObservableCollection ?

Related

How can I set the BindingContext of each view in a CarouselView?

I'm trying to let each view in a CarouselView have the same BindingContext object as the parent ContentPage. I've tried the following which doesn't seem to work. MainPage.xaml is the page that is initialized at runtime. It holds a CarouselView with four ContentViews holding "pages" of functionality I can swipe back and forth between from the MainPage.
MainPage.xaml:
...
<CarouselView Grid.Row="1" Grid.ColumnSpan="4"
Position="{Binding CarouselPosition}"
HorizontalScrollBarVisibility="Never">
<CarouselView.ItemsSource>
<x:Array Type="{x:Type ContentView}">
<local:HomeView></local:HomeView>
<local:NewsView></local:NewsView>
<local:ChartsView></local:ChartsView>
<local:SettingsView></local:SettingsView>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding .}" BindingContext="{Binding BindingContext, Source={x:Reference mainPage}}"/>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
...
Basically, I want to be able to set the BindingContext for each of these ContentViews to be the same as the parent's. I've also read that the ContentViews should be able to inherit the BindingContext sometimes, but it doesn't seem to be happening in this situation.
Thanks.
This is because this kind of control doesn't inherit its BindingContext from its parent but it has its own BindingContext set to the item of the collection binded to the ItemsSource which makes sense.
Let's say you want to display a collection of User. The DataTemplate will be the user interface of a User. You want to display some properties of a User, not your ViewModel.
If you want to bind to something exposed in the ViewModel and not the User, you have to bind the BindingContext of your element with either a RelativeSource or by targeting an element by its x:Name.
Exemple : to bind a button inside your DataTemplate to a command exposed in your ViewModel (not in User), you need to do that :
<Button
Text="Try me"
Command="{Binding
Path=BindingContext.MyViewModelCommand,
Source={x:Reference xNameOfParentOutsideDataTemplateOrThePage}" />
To make it easier to understand, what it does is : I want to bind to something on the control called xNameOfParentOutsideDataTemplateOrThePage (x:Name="xNameOfParentOutsideDataTemplateOrThePage"). On this control, I want to a property of its BindingContext (most of the time, your view model).
Instead of x:Reference, you can also use a RelativeSource binding.

Binding CommandParameter on ItemsControl Tap event

I'm using an ItemsControl, and I want to identify which item was selected on the Tap command. My xaml is defined here:
<ItemsControl ItemsSource="{Binding AllMyItems}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<cmd:EventToCommand Command="{Binding ItemSelectedCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
.... item template ....
and here is my view model:
public RelayCommand<MyItem> ItemSelectedCommand { get; private set; }
public MainViewModel()
{
ItemSelectedCommand = new RelayCommand<MyItem>(ItemSelected);
}
private void ItemSelected(MyItem myItem)
{
throw new NotImplementedException();
}
The event to command works, but when I get to the ItemSelected method, myItem is either Null, or I get an exception casting it (depending on how I define the CommandParameter in the xaml).
I can do this if I use a ListBox and set CommandParameter="{Binding SelectedItem, ElementName=MyItemsList"}
Any ideas on how to do this with ItemsControl? Or does the perf difference not make much of a difference between the two in Mango?
Your Tap Event is occuring on the ItemsControl , you should place your EventToCommand inside the ItemTemplate , some XAML to clear the things for you
<ItemsControl ItemsSource="{Binding AllMyItems}">
<ItemsControl.ItemTemplate>
<...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<cmd:EventToCommand Command="{Binding ItemSelectedCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</...>
</ItemsControl.ItemTemplate>
...

assigning the result of variable into textblock

I'm trying to get the result of variable into a textblock.text proprety, I'm using
this code:
bool isavailable = NetworkInterface.GetIsNetworkAvailable();
result = isavailable.ToString();
<TextBlock Height="62" HorizontalAlignment="Left" Margin="12,60,0,0"
Name="textBlock1" Text="{Binding result}" VerticalAlignment="Top"
Width="400" Foreground="White" TextWrapping="Wrap" />`
Do you need to keep the binding? The simplest approach here would be to simply use:
textBlock1.Text = result;
However, the better approach would be to use a ViewModel implementing INotifyPropertyChanged with an appropriate property. Then you would make your TextBlock bind to the property, and set the property from your code. The property would raise the appropriate event, and the UI would update accordingly.

Passing Object rather than selectedIndex from Databound listbox

I'm having an issue when I try to pass the selectedIndex of my list from my "List" screen.
On my List screen I have the following binding:
Code Behind:
lbPrograms.ItemsSource = App.ViewModel.Items;
XAML:
<ListBox x:Name="lbPrograms" ItemsSource="{Binding Items}" SelectionChanged="lbPrograms_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="DataTemplateStackPanel" Orientation="Horizontal">
<Image x:Name="ItemImage" Source="/images/ArrowImg.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/>
<StackPanel>
<TextBlock x:Name="ItemText" Text="{Binding programName}" Margin="-2,-13,0,0" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock x:Name="DetailsText" Text="{Binding createDate}" Margin="0,-6,0,3" Style="{StaticResource PhoneTextSubtleStyle}"/>
<TextBlock x:Name="programId" Text="{Binding programId}" Margin="0,-6,0,3" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
<!--<Image x:Name="ItemFavs" Source="/images/favs.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/>
<Image x:Name="ItemDelete" Source="/images/delete.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/>-->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In my detail screen I look up using the selectedIndex value:
App.ViewModel.Refresh();
DataContext = App.ViewModel.Items[index].nValDictionary;
However, since I can't figure out how to just update a value in my iEnumerable collection I have been removingAt[index] and then re-adding to the collection.
So can anyone tell me, how do use update an existing element in my collection? If not, can I pass the programId (that is in my binding) instead of the selectedIndex as the indexes are getting all messed up after the Delete/Add functionality.
Please Advise.
UPDATE:
After speaking in several forums I should clear up that I am implement INotifyChanged Event on my properties in my object.
Basically the following snippet of code is my current issue:
private void FavBtn_Click(object sender, EventArgs e)
{
foreach (var item in App.ViewModel.Items)
{
if ((item.currentProgram == true) && (item.programId != index))
{
item.currentProgram = false;
}
if (item.programId == index)
{
item.currentProgram = true;
}
}
When I run this everything looks to be ok.
However, when I navigate to another page, I re-load the object and the changes are lost. It is almost like I need to save them before navigating, however, if I do a item.Save(); I get duplicates in my list.
I'm guessing you haven't implemented INotifyPropertyChanged on your Items class yet.
Implementing this will allow updates made in these objects to be updated through your data bindings.
Here's a walkthrough on how to implement INotifyPropertyChanged.
How to: Implement the INotifyPropertyChanged Interface
Is App.ViewModel.Items of type ObservableCollection<T>?
If so, when you modify a property of one of the collection items and raise a property change event (via INotifyPropertyChanged) indicating the collection property that your ListBox.ItemsSource is bound to, the DataTemplate bindings will do the rest.

Pushpin with EventToCommand

I am trying to adapt the UsingBingMaps sample included in the Windows Phone 7 TrainingKit (http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=ca23285f-bab8-47fa-b364-11553e076a9a) to use MVVM-Light toolkit. I am trying to set up a command to the Pushpin's MouseLeftButtonUp event using EventToCommand but the command does not get executed. Below is the code of the pushpin:
<my:Pushpin Style="{StaticResource PushpinStyle}"
Location="{Binding Location}"
Background="{Binding TypeName, Converter={StaticResource PushpinTypeBrushConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<cmd:EventToCommand Command="{Binding DataContext.PushpinClickCommand, ElementName=HomePage}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Image Source="{Binding Icon}" />
</my:Pushpin>
Am I missing anything? Was anyone able to use EventToCommand with the Pushpin object?
What are you trying to do with the command?
I can get a command to fire using this, but i cant seem to get the object details from the arguments passed.
I have used this in silverlight, which I think is directly usable in WP7 (please correct me if I am mistaken)
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<cmd:EventToCommand Command="{Binding Path=pinSelCommand}" PassEventArgsToCommand="True" ></cmd:EventToCommand>
</i:EventTrigger>
</i:Interaction.Triggers>
In my viewmodel constructor I have
PolySelCommand = new RelayCommand<MouseButtonEventArgs>(PolySelCommandExecute);
in viewmodel class
public RelayCommand<MouseButtonEventArgs> pinSelCommand{ get; set; }
private voidpinSelCommandExecute(MouseButtonEventArgs e)
{
// < Your code >
}
Hope this helps out. If you work out how to pass the object details, please post back as I have problem on this post

Resources