Blend 4 Passing Data Context with Navigate To - xaml

I have a list of customers with various pieces of information. I have a list box with their names. When I select an entry I see more information about the customer on the screen. I want to "Navigate To" another screen when clicking on the user's name with more of their information. I can't figure out how to pass information about the entry to the next screen to accomplish this.
Here is the list box that the user chooses from to begin with.
<ListBox x:Name="scheduleListBox"
ItemTemplate="{DynamicResource ItemTemplate}"
ItemsSource="{Binding Collection}"
Margin="8,8,8,0"
Style="{DynamicResource ListBox-Sketch}"
Height="154"
VerticalAlignment="Top"/>
Here is the TextBlock that could be clicked to go to the other screen. It is changed based on what the user selected from the ListBox.
<TextBlock Text="{Binding Customer}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="150" Margin="104,0,0,0"
Style="{DynamicResource BasicTextBlock-Sketch}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<pi:NavigateToScreenAction TargetScreen="V02Screens.Customer_Status"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
I'm kind of hoping that there is something I can do in Expression Blend 4 or in the XAML.

In Windows 8, you can pass the entire object to the receiving page.
Like this:
// main page
private void ListBox_SelectionChanged_1
(object sender, SelectionChangedEventArgs e)
{
var _Item = (sender as ListBox).SelectedItem;
Frame.Navigate(typeof(MainPage), _Item);
}
// detail page
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DataContext = e.Parameter;
}
In WPF & SL, you can save reference to the SelectedItem in your View Model.
// main page
private void ListBox_SelectionChanged_1
(object sender, SelectionChangedEventArgs e)
{
var _Item = (sender as ListBox).SelectedItem;
MyModel.SelectedItem = _Item;
// TODO: navigate
}
// detail page
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DataContext = MyModel.SelectedItem;
}
I hope this helps.

In WPF you can supply an object to the Navigate command which contains anything you want, including whatever data you might want to show on the next page. Then on the target page (the one you navigate to), you have to handle the load completed event.
In your first page you might navigate with...
this.NavigationService.Navigate( somePage, someContainerObject );
Then you might retrieve it on somePage with...
// Don't forget to subscribe to the event!
this.NavigationService.LoadCompleted += new LoadCompletedEventHandler(container_LoadCompleted);
...
void container_LoadCOmpleted( object sender, NavigationEventArgs e)
{
if( e.ExtraData != null )
// cast e.ExtraData and use it
}

Related

UWP Binding: Changing backgrounds in XAML using C#

Suppose I am making a simple UWP application which navigates through several pages. I would like to have a common background for all pages, depending on which background a user has selected from the Settings page.
I have a SettingsPage.xaml with a comboBox (and Grid Background that needs to change):
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ComboBox Name="ColourSelect" SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem Name="Red">Red</ComboBoxItem>
<ComboBoxItem Name="Green">Green</ComboBoxItem>
<ComboBoxItem Name="Blue">Blue</ComboBoxItem>
</ComboBox>
</Grid>
Which interfaces with my SettingsPage.xaml.cs file:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Change background
if (Red.IsSelected) { } // Change to Red.png
else if (Green.IsSelected) { } // Change to Green.png
else if (Blue.IsSelected) { } // Change to Blue.png
}
I have set up my App.xaml to contain a background resource, but I'm not sure how to bind it to the C# in Settings.xaml.cs.
<Application.Resources>
<Style TargetType="Grid" x:Key="CommonBackground">
<Setter Property="Background" Value="{ <!-- Some image. How to bind? --> }"
</Style>
</Application.Resources>
What should I return to bind the user decision to the Application resources?
Thank you in advance!
This requires few changes in different pieces of application. Follow my steps.
In this case I a am creating two Resources. One that will maintain the Settings Combobox Colour Scheme. Second one is BitMapImage in Resource.
So my Application.Resource will look something like below.
<Application.Resources>
<image:BitmapImage x:Key="BackgroundSource" UriSource="ms-appx:///Assets/Red.png" />
<x:String x:Key="BackgroundBrush">Red</x:String>
</Application.Resources>
Make sure you are adding xmlns:image="using:Windows.UI.Xaml.Media.Imaging" in your App.xaml.
Now Create a Static Method inside App.xaml.cs that will be used to update Background to the Page during Run time. It should be something like below.
public static void UpdateBGColors(string Color)
{
switch (Color)
{
case "Red":
Current.Resources["BackgroundSource"] = "ms-appx:///Assets/Red.png";
break;
case "Green":
Current.Resources["BackgroundSource"] = "ms-appx:///Assets/Green.png";
break;
case "Blue":
Current.Resources["BackgroundSource"] = "ms-appx:///Assets/Blue.png";
break;
default:
Current.Resources["BackgroundSource"] = "ms-appx:///Assets/Red.png";
break;
}
}
Now Your combobox_SelectionChanged should look like below.
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cb = sender as ComboBox;
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
localSettings.Values["BackgroundBrush"] = (cb.SelectedValue as ComboBoxItem).Content;
App.UpdateBGColors((cb.SelectedValue as ComboBoxItem).Content.ToString());
}
Now you need to wire up the Background of each page to the Resource BackgroundSource. So anywhere you want the background to be set based on settings add below lines of code
<Grid>
<Grid.Background>
<ImageBrush ImageSource="{StaticResource BackgroundSource}" />
</Grid.Background>
......
</Grid>
At this point, if you change the setting in setting page and if you navigate back to original page that you came into setting page, The background should be set automatically to whatever you selected in Settings.
But you also want to make sure the same background is loaded when the app is opened next time. To do that in App.xaml.cs, Add below lines in the beginning of OnLaunched Event.
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
if (localSettings.Values["BackgroundBrush"] != null)
{
UpdateBGColors(localSettings.Values["BackgroundBrush"].ToString());
}
Since in settings page, you are saving BackgroundBrush Everytime you change the Combobox Item, Whenever your app is loading, Based on the BackgroundBrush BackgroundSource will be assigned to correct Uri and will be used as Page Backhground.
Full Repo is available Here
Good Luck.
[Update] You can use this, and after save your settings.
SettingsPage.xaml
<Grid>
<Grid.Background>
<ImageBrush x:Name="colorImage" Stretch="UniformToFill"/>
</Grid.Background>
<ComboBox Name="ColourSelect" SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem Name="Red">Red</ComboBoxItem>
<ComboBoxItem Name="Green">Green</ComboBoxItem>
<ComboBoxItem Name="Blue">Blue</ComboBoxItem>
</ComboBox>
</Grid>
SettingsPage.xaml.cs
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (Red.IsSelected)
{
ChangeColorImage("ms-appx:///Assets/Red.png");
}
else if (Green.IsSelected)
{
ChangeColorImage("ms-appx:///Assets/Green.png");
}
else if (Blue.IsSelected)
{
ChangeColorImage("ms-appx:///Assets/Blue.png");
}
}
private void ChangeColorImage(string imageUrl)
{
// using Windows.UI.Xaml.Media.Imaging;
BitmapImage imageSource = new BitmapImage(new Uri(imageUrl));
colorImage.ImageSource = imageSource;
}

How to change the Button content as CamelCasing in Windows phone 8.1 Message dialog

How to change the Button content as CamelCasing in Windows phone 8.1 Message dialog?
private async void Button_Click(object sender, RoutedEventArgs e)
{
MessageDialog msg = new MessageDialog("Do you want to continue?");
msg.Commands.Add(new UICommand("Ok", (command) => { }));
msg.Commands.Add(new UICommand("Cancel", (command) => { }));
await msg.ShowAsync();
}
I want to change the ok as Ok and cancel as Cancel.
If you want a custom dialog you need to use a different control. The MessageDialog always lower cases the buttons to match the system style and is not generally customizable.
If you use a ContentDialog you can customize it fairly extensively, and it doesn't try to fix the case of its buttons. You'll probably want to create your own ContentDialog class (there's a template under Add.New Item...) with your desired contents, but here's a quick content-free example:
ContentDialog cd = new ContentDialog();
cd.Title = "My Title";
cd.PrimaryButtonText = "CoNtInUe";
cd.SecondaryButtonText = "sToP";
await cd.ShowAsync();
Also note that the guidelines for message dialogs suggest using clear and specific verbs rather than generic OK/Cancel.
Use Content Dialog box like this:
Add this code inside your xaml.
<ContentDialog x:Name="AlertMessage" Background="#363636" IsSecondaryButtonEnabled="True" SecondaryButtonText="Cancel" IsPrimaryButtonEnabled="True" PrimaryButtonText="Ok" >
<ContentDialog.Content>
<StackPanel Name="rootStackPanel" Height="Auto" >
<StackPanel Margin="0">
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock x:Name="HeadingText" x:FieldModifier="public" Style="{StaticResource ApplicationMessageBoxHeadingStyle}" Text="Alert" />
<Image Margin="10,05,0,0" Source="/Assets/Images/alert.png" Width="35"></Image>
</StackPanel>
<TextBlock x:FieldModifier="public" x:Name="ContentText" Style="{StaticResource ApplicationMessageBoxErrorStyle}" Text="Are you sure you want to log off ?" />
</StackPanel>
</StackPanel>
</ContentDialog.Content>
</ContentDialog>
And call this like that in your code:
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
MessageBox();
}
private async void MessageBox()
{
ContentDialogResult LogoutDialog = await AlertMessage.ShowAsync();
if (LogoutDialog == ContentDialogResult.Primary)
{
// User pressed Ok.
}
else
{
// User pressed Cancel or the back arrow.
// Terms of use were not accepted.
}
}
Here is the code:
CustomMessageBox messagebox = new CustomMessageBox()
{
Caption = "Do you want to continue?",
LeftButtonContent = "Ok",
RightButtonContent = "Cancel"
};

Listview and Drag Item Windows Phone 8.1

I'm scruiggling with Windows Phone behavior. And maybe you could help me out somehow.
I want to have a listview from which I can drag items to another Gridview.
So far I got dragging enabled by setting ReorderMode = "Enabled". Doing this has some drawbacks.
1. I'm not able to scroll in my listview anymore
2. I can't select items anymore
3. I don't want the items to be reordered
What I want to have:
1. When holding an item, I want to drag this to another gridview
2. I want still be able to scroll in the listview
3. I still want to be able to select items
Is that somehow possible to do in Windows Phone 8.1?! Can I do my own dragging? Is yes, how should I start?!
Many thanks for any advise
ReorderMode isn't want you want in this case. Here's some basic functionality to do this between two ListViews:
<StackPanel Orientation="Horizontal" Width="800">
<ListView x:Name="ListView1" HorizontalAlignment="Left" DragItemsStarting="ListView_DragItemsStarting" AllowDrop="True" CanDragItems="True" CanReorderItems="True" Drop="ListView_Drop"/>
<ListView x:Name="ListView2" HorizontalAlignment="Right" DragItemsStarting="ListView_DragItemsStarting" AllowDrop="True" CanDragItems="True" CanReorderItems="True" Drop="ListView_Drop"/>
</StackPanel>
ObservableCollection<string> AlphabetList;
ObservableCollection<string> NumberList;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
AlphabetList = new ObservableCollection<string>();
AlphabetList.Add("A");
AlphabetList.Add("B");
AlphabetList.Add("C");
AlphabetList.Add("D");
AlphabetList.Add("E");
AlphabetList.Add("F");
AlphabetList.Add("G");
AlphabetList.Add("H");
AlphabetList.Add("I");
AlphabetList.Add("J");
ListView1.ItemsSource = AlphabetList;
NumberList = new ObservableCollection<string>();
NumberList.Add("0");
NumberList.Add("1");
NumberList.Add("2");
NumberList.Add("3");
NumberList.Add("4");
NumberList.Add("5");
NumberList.Add("6");
NumberList.Add("7");
NumberList.Add("8");
NumberList.Add("9");
ListView2.ItemsSource = NumberList;
}
IList<object> DraggedItems;
private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
DraggedItems = e.Items;
}
private void ListView_Drop(object sender, DragEventArgs e)
{
ListView ThisListView = sender as ListView;
ObservableCollection<string> AddingOC = (ThisListView.Name == "ListView1" ? AlphabetList :NumberList);
ObservableCollection<string> RemovingOC = (ThisListView.Name == "ListView1" ? NumberList : AlphabetList);
if (AddingOC.Contains(DraggedItems[0])) return;
foreach (string O in DraggedItems)
{
RemovingOC.Remove(O);
AddingOC.Add(O);
}
}

ListView Not updating if a delete an item

I have a listView which is set to Mode=TwoWay, which i thought was suppose to refresh the views, if the underlying data changed.
However, while the item is deleted correctly, the item still remains on the list, until I exit and return to the page.
Xaml:
<ListView ItemsSource="{Binding Path=items, Mode=TwoWay}" >
<DataTemplate>
...
<Button x:Name="btn_delete_item" Click="btn_delete_item_Click" >
</Button>
Behind code:
private void btn_delete_item_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
itemType item = button.DataContext as itemType;
items.Remove(item);
}
In order to fully support data binding, your Items collection must notify about changes, i.e. whether items are added, removed, replaced or moved. This notification is done by implementing the INotifyCollectionChanged interface. The framework's List<T> type does not implement this interface, but ObservableCollection<T> does.
So you could simply change the type of your Items property:
public ObservableCollection<ItemType> Items { get; set; }

How to set SelectedItem for a ColumnSeries chart from the ViewModel

I have a ColumnSeries chart where I want to control the selected item from the view model. I do this by binding the the SelectedItem of the chart to an object on the view model.
<chartingToolkit:Chart Grid.Row="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="0" MinHeight="200" Margin="0" x:Name="ratingsChart" Style="{StaticResource ChartWithoutLegendStyle}">
<chartingToolkit:Chart.Series>
<chartingToolkit:ColumnSeries x:Name="chartRatingColSeries" IsSelectionEnabled="True"
SelectedItem="{Binding SelectedRatingDistribution, Mode=TwoWay}"
ItemsSource="{Binding RatingsList}"
IndependentValueBinding="{Binding RatingName}"
DependentValueBinding="{Binding NumberOfGoodies}">
</chartingToolkit:ColumnSeries>
</chartingToolkit:Chart.Series>
</chartingToolkit:Chart>
There are various elements on the page which will force the chart's data to be reloaded (via a web service). When I need to reload the charts data (from the view model), I want to set the SelectedItem of the chart to the very first data point. This appears to work EXCEPT the chart does not visually show (in red, by default) the selected item. Here is sample code that reloads data after web service call and resets selected item:
private RatingDistribution _selectedRatingDistribution = new RatingDistribution();
public RatingDistribution SelectedRatingDistribution
{
get { return _selectedRatingDistribution; }
set
{
_selectedRatingDistribution = value;
RaisePropertyChanged("SelectedRatingDistribution");
}
}
private ObservableCollection<RatingDistribution> _lstRatings = new ObservableCollection<RatingDistribution>();
public ObservableCollection<RatingDistribution> RatingsList
{
get { return _lstRatings; }
set
{
_lstRatings = value;
RaisePropertyChanged("RatingsList");
}
}
private void GetRatingsDistributionCompleted(object sender, GetRatingsDistributionCompletedEventArgs e)
{
IsBusy = false;
RatingsList.Clear();
foreach (RatingDistribution rd in e.Result)
RatingsList.Add(rd);
SelectedRatingDistribution = RatingsList[0];
}
Setting the SelectedRatingDistribution from the View model will not visually show the selected item on the chart in red. Any ideas??
Update:
So if I click on a column, the chart correctly shows the selected item in red as so:
But If I set the SelectedItem from view model, the column will not be displayed in red (as the selected item)
Changed function below fixes problem..
private void GetRatingsDistributionCompleted(object sender, GetRatingsDistributionCompletedEventArgs e) {
RatingsList.Clear();
foreach (RatingDistribution rd in e.Result)
RatingsList.Add(rd);
App.Current.RootVisual.Dispatcher.BeginInvoke(new Action(delegate() { SelectedRatingDistribution = RatingsList[0]; }));
}