How can I page refresh without Navigation from my MvvM Light ViewModel - silverlight

How do I update a nested ListBox in my viewmodel (Mvvm Light) without page navigation after the initial view has been displayed. Currently I am doing a re-entrant page navigation using a changing querystring - there must be a better way?
RaisePropertyChanged is having no effect although I can see the data is populated with the correct data when the callback from the soap request triggered via OpenCallingPoints has fired.
The grid I am trying to populate with soap data is CallingPointsGrid
Short version of the code...
<ListBox x:Name="ResultsListBox" Margin="0" VerticalAlignment="Top" ItemsSource="{Binding JourneyLegs, Mode=TwoWay}" Background="{StaticResource BackgroundWhiteGradientBrush}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="StationItem" Orientation="Vertical" VerticalAlignment="Top" background="{Binding id, Converter={StaticResource myconverter}}">
<Grid Name="CallingPointsGrid" Margin="15,10,55,10" Visibility="{Binding JourneyCallingPoints, Converter={StaticResource CallingPointsVisibilityConverter}}" Background="{StaticResource BackgroundWhiteGradientBrush}">
<ListBox Grid.Row="1" Name="CallingPointsListBox" DataContext="{Binding}" VerticalAlignment="Top" ItemsSource="{Binding JourneyCallingPoints, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Top" Orientation="Horizontal">
<TextBlock Margin="0" VerticalAlignment="Center" HorizontalAlignment="Left" Width="210" x:Name="Destination" Foreground="Black" Text="{Binding stationName}" />
<TextBlock Margin="5,0,5,0" VerticalAlignment="Center" HorizontalAlignment="Left" Width="75" x:Name="ScheduledDepartureTime" FontWeight="Bold" Foreground="{StaticResource BackgroundBlueLightSolidColor}" Text="{Binding timetable.scheduledTimes.arrival, StringFormat=\{0:HH:mm\}}" />
<TextBlock Margin="5,0,5,0" VerticalAlignment="Center" HorizontalAlignment="Left" Width="75" x:Name="ScheduledArrivalTime" FontWeight="Bold" Foreground="{StaticResource BackgroundBlueLightSolidColor}" Text="{Binding timetable.scheduledTimes.departure, StringFormat=\{0:HH:mm\}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger SourceName="ResultsListBox" EventName="Tap">
<i:EventTrigger.Actions>
<local:OpenCallingPoints />
</i:EventTrigger.Actions>
</i:EventTrigger>
</i:Interaction.Triggers>

You might look at this:
http://matthamilton.net/madprops-mvvmlight-screenconductor
I was going to suggest you look at Caliburn Micro and was searching around to see if Mvvm-Light had something similar. That article talks about that.
That's one of the things I really like about CM, when you inherit your ViewModel from Screen you automatically get OnInitialize, OnActivate, OnDeactive, OnViewLoaded, and OnViewReady methods you can override. So in this case you'd stick that logic in OnActivate.
On windows phone CM will also auto parse out the query string parameters and populate a property on your VM with them.
It looks like the screen conductor allows you to do similar with mvvm-light.

Related

Commanding with Static Items of Listbox using MVVM

I have a list box in my view with three static items(Name,Age,Gender), and I want my ViewModel to do something when an item in the ListBox is selected. I want to do this without any code-behind, using the MVVM pattern.
My goal is to navigate to a page when an item is selected also the items stated above does not come from an observable list, it is hardcoded in my XAML. How would I do that? Please teach me. If you don't mind to send a sample, that would be a great help. Thanks much in advance.
<ListBox x:Name="lbviewlist">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<Command:EventToCommand Command ="{Binding ViewCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.Items>
<StackPanel x:Name="lbiview1" Orientation="Vertical">
<ListBoxItem Content="Name" FontSize="35" Margin="10,0,0,0"
Foreground="OrangeRed"/>
<TextBlock TextWrapping="Wrap" Text="View name of the patient"
FontSize="25" Margin="10,0,0,0" Foreground="White"/>
</StackPanel>
<StackPanel x:Name="lbiview2" Orientation="Vertical">
<ListBoxItem Content="Age" FontSize="35" Margin="10,20,0,0"
Foreground="OrangeRed"/>
<TextBlock TextWrapping="Wrap" Text="View age of the patient"
FontSize="25" Margin="10,0,0,0" Foreground="White"/>
</StackPanel>
<StackPanel x:Name="lbiview3" Orientation="Vertical">
<ListBoxItem Content="Gender" FontSize="35" Margin="10,20,0,0"
Foreground="OrangeRed"/>
<TextBlock TextWrapping="Wrap" Text="View the gender of the patient"
FontSize="25" Margin="10,0,0,0" Foreground="White"/>
</StackPanel>
</ListBox.Items>
</ListBox>
You can use data binding to bind the SelectedItem of the ListBox to a property on your view model. Then, in the setter of your view model property, you can run the logic you need to when the selected item changes.
<ListBox SelectedItem="{Binding MySelectedItem}" ... />
Update
Ok, firstly I would strongly recommend (no insist) that you use an MVVM framework. If you're doing MVVM, then you need to use a framework.
Next, there's no reason why these list items can't be on your view model. It would certainly make your view a lot cleaner.
Then you can set your ListBox ItemsSource to bind to your view model collection, and then use data templating in your view to render each item in the list consistently.
E.g. your view can end up something like:
<ListBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Value}" ... />
<TextBlock Text="{Binding Description}" ... />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Much cleaner, I think you'll agree.

WPF TreeView multiple itemsSource

I want to display the following using a wpf TreeView:
My objects are different, there is no Base class or Interface, I must define a HierarchicalDataTemplate for each item, STOP for example I can add just one ItemSource "Deliveries" but I want to add the pickups also for this stop.
<!-- DELIVERY-->
<DataTemplate x:Key="DeliveryDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="DeliveryId" Margin="3,3" />
<TextBlock Text="{Binding DeliveryStatus}" VerticalAlignment="Center" Margin="5" />
<TextBlock Background="{Binding StopStatus, Converter={StaticResource StatusConverter}}" Width="16" Height="16" />
</StackPanel>
</DataTemplate>
<!-- STOP -->
<HierarchicalDataTemplate x:Key="StopTemplate"
ItemsSource="{Binding Deliveries}"
ItemTemplate="{StaticResource DeliveryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Stop" Margin="3,3" />
<TextBlock Text="{Binding StopId}" Margin="3,3" />
<TextBlock Background="{Binding StopStatus, Converter={StaticResource StatusConverter}}" Width="16" Height="16" Margin="3,3" />
</StackPanel>
</HierarchicalDataTemplate>
<!-- ROUTE -->
<HierarchicalDataTemplate x:Key="RouteTemplate"
ItemsSource="{Binding Stops}"
ItemTemplate="{StaticResource StopTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Route" Margin="5,5" />
<TextBlock Text="{Binding RouteId}" Margin="5,5" />
<TextBlock Background="{Binding RouteStatus, Converter={StaticResource StatusConverter}}" Width="16" Height="16" Margin="5,5" />
</StackPanel>
</HierarchicalDataTemplate>
I have a collection of Routes, each Route has Stops, each Stop has Deliveries and Pickups, each Delivery has its items each item has its own items and so on... How to solve this?
This sounds like a heterogenous datasource problem. I think this solution might be what you are looking for.
I like this answer because it need some very short codes.
WPF Treeview Databinding Hierarchal Data with mixed types
And you might need reading this question to import the System.Windows.Data.ObservableCollection Class. To be short, it can only be imported in a Wpf Library or so, not in a normal .net Class Library.
Cannot Import System.Windows.Data

How do I Raise an Event when the Binding is completed?

I have a TextBox in my application that i am developing and the binding is done in the xaml
I want to be able to raise an event when the binding of the TextBox Text Property is completed meaning when the text is loaded/changed through binding into the TextBox how do i achive this?
I tried TextChanged Event also Loaded Event but no luck right after the Binding is complected so how do i do it?
<ListBox x:Name="listBoxCategories" Background="Transparent" BorderThickness="0" Grid.Row="4" Grid.ColumnSpan="2" Margin="0" Padding="0" ItemContainerStyle="{StaticResource ListBoxItemStyle}" ItemsSource="{Binding ElementName=discussion_categoryDomainDataSource, Path=Data}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="stackPanelCategory" Orientation="Vertical" Margin="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<TextBlock x:Name="TextBlockCategoryId" Text="{Binding Path=CategoryID}" />
<toolkit:Expander IsExpanded="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Style="{StaticResource ForumExpanderStyleRight}">
<toolkit:Expander.Header>
<TextBlock FontSize="16" FontWeight="Bold" Foreground="White" Margin="4,0,4,0" Text="{Binding CategoryName}" LayoutUpdated="TextBlock_LayoutUpdated" />
</toolkit:Expander.Header>
<ListBox x:Name="listBoxBoards" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Transparent" BorderThickness="0" Margin="0" Padding="0" ItemContainerStyle="{StaticResource ListBoxItemStyle}" ItemsSource="{Binding CategoryBoards}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0" HorizontalAlignment="Stretch" x:Name="GridBoard">
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</toolkit:Expander>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
at this line
<TextBlock x:Name="TextBlockCategoryId" Text="{Binding Path=CategoryID}" />
I want an event where when the Binding is completed i want to give a different data source for the list box under the parent stack panel so i need the binding event so when i have the catedory id int he text block which later will be hidden in the xaml ( which now is not collapsed for testing reasons )
This is a slightly peculiar thing to want to do, it might help if you tell us why you are wanting to do this?
However, with no other information to hand, I will propose a solution.
If the TextBox API events do not provide the infomation you need, try handing the LayoutUpdated event. This event fires each time layout occurs, which is typically as elements ae added to the visual tree. WHen this event fires inspect your TextBox.Text property to see if it is set.
This solved the problem for me :)
<TextBlock FontSize="16" FontWeight="Bold" Foreground="White" Margin="4,0,4,0" Text="{Binding CategoryName}" Loaded="TextBlock_Loaded" />
Loaded event in the inner Text block rather than the upper textblock because by the time this is loaded the upper text block's text is already bound so i can retrive the ID :)

Listbox on one page calling SelectionChanged event handler of ListBox on AnotherPage?

I have a two pages say Main.xaml and Details.xaml.Each page has a ListBox and I am setting each of it to a collection in ViewModel(Same collection).The strange thing is that when i select an item in Details page it calls the SelectionChanged event handler on Main page and Details page.Is this a bug?
I have solved the problem by unhooking SelectionChanged eventhandler in OnNavigatedFrom() method.
EDIT
In Main.Xaml I have something like below:
<ListBox Name="MainDataListBox" Margin="8,113,8,8" ItemsSource="{Binding DataList}" SelectionChanged="MainDataListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Border BorderThickness="3" BorderBrush="#A5FFFFFF" Width="80" Margin="0,20,0,20" Height="60">
<Image Source="{Binding ImageUrl, Mode=OneWay}" VerticalAlignment="Stretch" Margin="0,0,0,0" Width="80" Height="60" Stretch="Fill" />
</Border>
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" FontSize="40" FontWeight="Normal" VerticalAlignment="Center" Margin="30,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In Details.xaml also I have same kind of ListBox:
<ListBox Name="DetailDataListBox" Margin="8,113,8,8" ItemsSource="{Binding DataList}" SelectionChanged="DetailDataListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Border BorderThickness="3" BorderBrush="#A5FFFFFF" Width="80" Margin="0,20,0,20" Height="60">
<Image Source="{Binding ImageUrl, Mode=OneWay}" VerticalAlignment="Stretch" Margin="0,0,0,0" Width="80" Height="60" Stretch="Fill" />
</Border>
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" FontSize="40" FontWeight="Normal" VerticalAlignment="Center" Margin="30,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Both of the Pages Main and Details have seperate EvenHandlers MainDataListBox_SelectionChanged and DetailDataListBox_SelectionChanged.
The problem is when i select an Item in Details Page MainDataListBox_SelectionChanged is called first and then DetailDataListBox_SelectionChanged.
Also my viewmodel is a static one in App.cs and I am setting the data context of both these pages to same viewmodel.
Thanks and Regards
vaysage
As both listsboxes were bound to the same dataset a change in the selected time in one list would have affected the other.
Obviosuly you're found a work around but I'd recommend having a unique view model for each page. If the page is just a different way of displaying the same data use a single page and alter the display as appropriate. (Creating your own visual states may be a good way to do this.)

Tab order and index in WPF using the MVVM pattern

I'm having an issue with tabbing through the controls on a WPF application using the MVVM pattern. I have the following XAML which defines a tree structure
<Grid Background="Transparent" Margin="10">
<TreeView ItemsSource="{Binding FirstLevelNavigableViewModels}" Background="Transparent"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="0"
ItemContainerStyle="{StaticResource TreeViewItemStyle1}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type ViewModel:VendorViewModel}" ItemsSource="{Binding Children}">
<View:VendorView HorizontalContentAlignment="Stretch" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ViewModel:ProductViewModel}">
<View:ProductView HorizontalContentAlignment="Stretch" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
When the treeview is loaded, the XAML for the "ProductView" is as follows
<Border Margin="0,2,2,2" CornerRadius="3" Background="#3FC7B299" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="109">
<StackPanel Orientation="Vertical" Margin="6,4">
<DockPanel>
<TextBlock DockPanel.Dock="Left" FontFamily="Segoe" FontSize="10" FontWeight="Medium"
Foreground="Black" Opacity="0.75"
Text="CALC. REG. PRICE"></TextBlock>
<Button Width="10" Height="10" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Padding="-4" Margin="0" Command="{Binding UserDefinedRetailPriceCommand}" Visibility="{Binding UserDefinedRetailPriceButtonView}">
<Image Width="10" Height="10" Source="/Arhaus.Pricing.Client;component/Styles/Images/error.png"></Image>
</Button>
</DockPanel>
<TextBox FontFamily="Segoe" FontSize="16" FontWeight="Medium" KeyboardNavigation.IsTabStop="True" KeyboardNavigation.TabIndex="{Binding RegularPriceTabIndex}"
Foreground="Black" Opacity="0.9" KeyboardNavigation.TabNavigation="Continue"
ebf:LostFocusBehaviour.LostFocusCommand = "{Binding LostFocusSugg}"
Text="{Binding NewSuggestedRetailPrice,Converter={StaticResource FormattingConverter}, ConverterParameter=' \{0:C\}', Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Background="#FFE6DED3" BorderBrush="#FFE6DED3" DataContext="{Binding StringFormat=\{0:c\}, NotifyOnValidationError=True}" Padding="0" TabIndex="1"></TextBox>
</StackPanel>
</Border>
I have the Tab Index bound to an integer that is ever increasing and bound as the treeview is loaded (I.E. I have it setup as tab index 1, 2, 3 etc. as each successive model is loaded).
I would like to be able to hit tab and jump to the next textbox in the treeview but when I click the TAB key, nothing happens. I'm not sure if I have the tabbing setup correctly but I'm very new to WPF and at a loss as to where and how to set the tabbing to make it work. I'm used to WinForms where you just set the tab index and go from there.
Thank you for your assistance, I apologize for the large code block.
I don't have a solution ready but some thoughts that maybe may help:
I don't know what RegularPriceTabIndex returns but probably it begins for each new TreeViewItem at the same index?
The same tab-index is given then multiple times because of repeating use of ProductView. Perhaps this leads to a problem. You can try setting FocusManager.IsFocusScope="true" for the ProductView. Maybe this helps.
Try also to set Control.IsTabStop="true" on the TextBox.

Resources