Description in UWP ComboBox - user-interface

I'm trying to get a combobox (or equivalent) to include a short description of the option in the dropdown as well as the title, as shown in this quick doodle I did:
dropdown doodle that I can't embed in question, sorry
I have tried googling for an option, but I didn't have much luck. Thanks!

As Luca Lindholm said, you need to cunstomize the ComboBox.ItemTemplate.
You can see the result.
Xaml code:
<ComboBox x:Name="combo" Width=" 200" Margin="20 0 0 0" SelectedIndex="0">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:UserSS">
<StackPanel>
<TextBlock Text="{x:Bind option}"/>
<TextBlock Text="{x:Bind option_desc}" Margin="20 0 0 0"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
cs code:
List<UserSS> list = new List<UserSS>();
for(int i = 0; i < 9; i++)
{
UserSS user = new UserSS
{
option = "Option" + i.ToString(),
option_desc = "Desc" + i.ToString()
};
list.Add(user);
}
combo.ItemsSource = list;

Well, you can choose to customize the ItemTemplate of the ComboBox, and by:
Creating a ViewModel for the object and a main ViewModel for the app...
Creating a DataTemplate and setting it as the ItemTemplate
of the ComboBox...
Using a ObservableCollection with your object ViewModel, in the main ViewModel, as an ItemsSource for your ComboBox...
and finally data binding the XAML inside the DataTemplate to the properties of the object viewmodel...
...you should be fine.
Regards

Related

How can I write a DataTemplate with list and page bindings in C#

I have been asked to change some code to C# for Xamarin from XAML.
Is there anyone here who could give me advice on how I can do this.
Here's an example of what I have in XAML. MyGrid is a grid with a label inside of it written in C# that has a Text and a TappedCmd binding.
<ContentPage x:Name="thisPage">
<StackLayout
BindableLayout.ItemsSource="{Binding ListOfText}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<MyGrid Text="{Binding Text}"
TapCommand="{Binding
Path=BindingContext.TappedCmd, Source={x:Reference Name=thisPage}}"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Is this something that's easy to do in C# and how can I do it or at least can someone give me some example of similar code that I can use to work from.
You could try something like below:
public YourPage()
{
var viewModel = ...;
var dataTemplate = new DataTemplate(()=>
{
var mygrid = new MyGrid ();
mygrid.SetBinding(MyGrid.TextProperty, "Text");
mygrid.SetBinding(MyGrid.TapCommandProperty, new Binding("TappedCmd", source: viewModel));
return mygrid;
});
StackLayout stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, viewModel.ListOfText);
BindableLayout.SetItemTemplate(stackLayout, dataTemplate);
Content = stackLayout;
}
you could refer to Bindable Layouts

Windows Phone: How to get image source value of an image tag inside a stack panel?

I have some stack panels. And each of stack panels has an image tag. The code look like this:
....
<StackPanel>
<Image Source="/Puzzle15;component/Images/Themes/Easy/p5.png" Tag="5"/>
</StackPanel>
<StackPanel>
<Image Source="/Puzzle15;component/Images/Themes/Easy/p6.png" Tag="6"/>
</StackPanel>
<StackPanel>
<Image Source="/Puzzle15;component/Images/Themes/Easy/p7.png" Tag="7"/>
</StackPanel>
...
I want to get image source value by using the code
for(int i = 0; i <= 14; i++)
{
String s = ((Image)((StackPanel)ContentPanel.Children[i]).Children[0]).Source.ToString();
MessageBox.Show(s);
}
And the result shows "System.Windows.Media.Imaging.BitmapImage"
Could you show me the way to get the source value??
Thanks!
var bms = ((Image)((StackPanel)ContentPanel.Children[i])
.Children[0]).Source as BitmapImage;
var addy = bms.UriSource.ToString();
By the way, the way you are doing this is antithetical to WPF (and silverlight, WP, Modern UI, etc etc) programming. I would strongly suggest you do some reading, some tutorials, learn what "View Model" means, and how to use Bindings. You will be better off in the end.

Why am I getting a "well-formedness constraint: unique attribute spec" (0xc00cee3c) error when I descend from LongListSelector

I'm trying to create a descendant class from the silverlight toolkit LongListSelector. Let's call it SimpleLonglistSelector. I started from the "Silverlight for Windows Phone Toolkit Source & Sample - Feb 2011.zip"
http://silverlight.codeplex.com/releases/view/60291
I created a new class:
public class SimpleLongListSelector : LongListSelector
{
public SimpleLongListSelector()
{
var itemsPanelTemplate = #"
<ItemsPanelTemplate xmlns='http://schemas.microsoft.com/client/2007'>
<toolkit:WrapPanel xmlns:toolkit='clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit' Orientation=""Horizontal""/>
</ItemsPanelTemplate>";
this.GroupItemsPanel = (ItemsPanelTemplate)XamlReader.Load(itemsPanelTemplate);
var groupItemTemplate = #"
<DataTemplate xmlns='http://schemas.microsoft.com/client/2007'>
<Border Width=""99"" Height=""99"" Background=""{StaticResource PhoneAccentBrush}"" Margin=""6"" IsHitTestVisible=""{Binding HasItems}"">
<TextBlock Text=""{Binding Key}""
FontFamily=""{StaticResource PhoneFontFamilySemiBold}""
FontSize=""36""
Margin=""{StaticResource PhoneTouchTargetOverhang}""
Foreground=""{StaticResource PhoneForegroundBrush}""
VerticalAlignment=""Bottom""/>
</Border>
</DataTemplate>";
this.GroupItemTemplate = (DataTemplate)XamlReader.Load(groupItemTemplate);
var groupHeaderTemplate = #"
<DataTemplate xmlns='http://schemas.microsoft.com/client/2007'>
<Border Background=""Transparent"">
<Border Background=""{StaticResource PhoneAccentBrush}"" Width=""75"" Height=""75"" HorizontalAlignment=""Left"">
<TextBlock Text=""{Binding Path=Key}""
Foreground=""{StaticResource PhoneForegroundBrush}""
Style=""{StaticResource PhoneTextExtraLargeStyle}""
VerticalAlignment=""Bottom""/>
</Border>
</Border>
</DataTemplate>";
this.GroupHeaderTemplate = (DataTemplate)XamlReader.Load(groupHeaderTemplate);
var itemTemplate = #"
<DataTemplate xmlns='http://schemas.microsoft.com/client/2007'>
<TextBlock Text=""{Binding Title}"" FontSize=""30""/>
</DataTemplate>";
this.ItemTemplate = (DataTemplate)XamlReader.Load(itemTemplate);
}
}
Then I added it to the LongListSelector example, in the same pivot as all of the other long list selectors:
<controls:PivotItem Header="SLLS">
<local:SimpleLongListSelector x:Name="simple" />
</controls:PivotItem>
Then I added it's source to be the same as the movies source in the LoadLinqMovies()
simple.ItemsSource = moviesByCategory;
Then run the code (I know it doesn't look pretty, that's because the bindings haven't been set up right, I do that so you know it's not the data. If you'd like, you can do it like this:
simple.ItemsSource = movies.GroupBy((m) => m.Title[0]).Select((c) => new PublicGrouping<char, Movie>(c));
That looks like I want it to look.
Well, in either case, this works as expected, except when I click on a group header. (any of the [by default blue] squares). I get a
WrappedException
The error message is:
0xc00cee3c
Which I think means:
well-formedness constraint: unique attribute spec
I don't think I've got a uniqueness problem. What am I doing wrong?
If you use the LongListSelector from the 7.1 toolkit, found at http://silverlight.codeplex.com/releases/view/71550, your sample code works as listed above. This must have been some bug in the original LLS...

Databinding PivotItems to ObservableCollection on WP7

I want to databind an ObservableCollection to a Pivot contronl in WP7 so that each object in my ObservableCollection becomes a PivotItem. This is the code I use:
<controls:Pivot x:Name="MainPivot" ItemsSource="{Binding Persons}">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding FullName}"/>
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text="{Binding LastName}"/>
<TextBlock Text="{Binding HomeTown}"/>
</StackPanel>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
This works and with tre items in my ObservableCollection I get three PivotItems. But when everything gets loaded the binding inside the DataTemplate won´t get updated. It is only when I scroll to the next PivotItem that the FirstName, LastName and HomeTown gets loaded.
Why is that? What am I missing?
Thanks
Check this discussion:
DataBound Pivot control is not creating the first PivotItem
I had the same problem, but the workaround with setting SelectedIndex=1 didn't suit me.
I found the other solution: when you adding the Item to your Persons collection you should first create a temp element and only when you fill all data add it to your Persons collection.
Person tempPers = new Person() { FullName = "Abduvaliev Edem", FirstName = "Edem", LastName = "Abduvaliev", HomeTown = "Sevastopol"};
Pesrons.Add(tempPers);
After doing a simple test i cannot reproduce this behavior. I i put a breakpoint inside the get block of the equivalent of FirstName with two items in my ObservableCollection i get two hits.
How did you detect that it is not bound? You cannot see the "next" pivotitems content, so how?
Sounds like there's some problem with the loading order - or with the notification code.
Check that you are correctly firing the PropertyChanged event when you set the properties on each of your FirstName, LastName and HomeTown members.
Here's how I do it. The problem for me is that the collection updates asynchronously in response to a web method call.
void Page_Loaded(object sender, RoutedEventArgs e)
{
_log.Debug("Page loaded.");
var vm = this.GetViewModel<TrendsViewModel>();
if (!vm.IsInitialized)
{
vm.PivotItems.CollectionChanged += (origin, args) =>
{
this.PivotControl.DataContext = null;
this.PivotControl.DataContext = vm;
};
vm.Initialize(this);
}
}
The key is hooking up an observer of the collection to which the Pivot items are bound and giving the data context a shake when it updates.

How to disable touch selection in listbox item in Windows Phone 7?

In the XAML template, I used a listbox to populate some dynamic data.
Now I want to disable touch selection in certain listbox items in Windows Phone 7. How to do that ?
I had done some little research, some people said that the selection event could be prevented in the listbox.
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/8eeed347-ede5-4a24-88f1-953acd16e774
Hope some smart guys could teach me how to solve the problem.
Thanks.
You could use the ItemsControl instead of ListBox. ItemsControl is like ListBox, but it comes without the selection stuff.
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Use ItemsControl wrapped in a ScrollViewer. This will give you the same effect without selection (and will allow you to scroll just like a ListBox does)
<ScrollViewer>
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
Try using a variable to store the last selected index.
If the user then selects an item which you don't want to handle the selection event for then set the selected index back to the stored value. If you do want to hand;e the selection changed event then be sure to update your stored value too.
You'll probably also want to avoid triggering the selection changed when you manually set the index (back).
A simple boolean flag could be used to track this.
Old question but it doesn't look answered. You can do it through code, manipulating the selected item and index, but that's ugly and cumbersome. Instead let's do it declaratively (the XAML way!) with your bound items.
First you'll need a ViewModel with a list of items. Each item needs (at minimum) a property to display and a property to determine if the item is enabled or not.
Here's a sample viewmodel for a single item in the list:
class MyViewModel : ViewModelBase
{
private string _title;
public string Title
{
get { return _title; }
set
{
if(value == _title) return;
_title = value;
RaisePropertyChanged("Title");
}
}
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
if(value == _isEnabled) return;
_isEnabled = value;
RaisePropertyChanged("IsEnabled");
}
}
}
The above example assumes MVVM Light for the ViewModelBase and the RaisePropertyChanged method, but you can do it with IPropertyNotified yourself (or any other MVVM library).
Next you'll have a listbox with markup similar to the following:
<ListBox ItemsSource="{Binding MyItems}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter IsHitTestVisible="{Binding IsEnabled}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
That's it. Now just load up some viewmodel with a list of items:
MainViewModel.MyItems = new ObservableCollection<MyViewModel>();
MainViewModel.MyItems.Add(new MyViewModel { Title = "Star Wars", IsEnabled = true });
MainViewModel.MyItems.Add(new MyViewModel { Title = "The Sound of Music", IsEnabled = false });
MainViewModel.MyItems.Add(new MyViewModel { Title = "Aliens", IsEnabled = true });
MainViewModel.MyItems.Add(new MyViewModel { Title = "Debbie Does Dallas", IsEnabled = false });
MainViewModel.MyItems.Add(new MyViewModel { Title = "True Grit", IsEnabled = false });
Only the sci-fi movies in this example are clickable.
Hope that helps.

Resources