I'm using Toolkit ListPicker in my Windows Phone 8 project and have begun localising it. I've run into a problem because i can't figure out how to do this with a ListPicker.
<toolkit:ListPicker x:Name="lstClubsPick"
FontSize="30"
Grid.Column="1"
VerticalAlignment="Center"
SelectionMode="Single"
HorizontalAlignment="Center"
SelectedIndex="{Binding KolleSelectedIndex, Mode=TwoWay}"
CacheMode="BitmapCache"
ExpansionMode="FullScreenOnly" >
<toolkit:ListPickerItem Content="{Binding Path=LocalizedResources.chooseClub, Source={StaticResource LocalizedStrings}}"/>
<sys:String>Choose</sys:String>
<sys:String>D1</sys:String>
<sys:String>D2</sys:String>
<sys:String>D3</sys:String>
<sys:String>D4</sys:String>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<cal:ActionMessage MethodName="ClubClicked">
<cal:Parameter Value="{Binding ElementName=lstPivot,Path=SelectedItem, Mode=TwoWay}"></cal:Parameter>
<cal:Parameter Value="{Binding ElementName=lstClubsPick,Path=SelectedItem, Mode=TwoWay}"></cal:Parameter>
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
So the problem I'm facing is that i don't know how to get <sys:String>Choose</sys:String> to look for a string in my AppResources.resx. I've tried this:
<toolkit:ListPickerItem Content="{Binding Path=LocalizedResources.chooseClub, Source={StaticResource LocalizedStrings}}"/>
instead of the <sys:string> but that makes my app crash. I've searched google and that was the only possible solution i could find. Anyone able to help me? Would be much appreciated.
EDIT 1: So I've updated my code with the solution from andreask but my ListPicker is not responding to the string i add in my viewModel.
private ObservableCollection<string> _data;
public ObservableCollection<string> Data
{
get
{
return _data;
}
set {
_data = value;
NotifyOfPropertyChange(() => Data);
}
}
Data = new ObservableCollection<string>();
Data.Add("Test");
<toolkit:ListPicker x:Name="lstClubsPick" FontSize="30" Grid.Column="1" VerticalAlignment="Center" SelectionMode="Single" HorizontalAlignment="Center" ItemsSource="{Binding Data}" SelectedIndex="{Binding KolleSelectedIndex, Mode=TwoWay}" CacheMode="BitmapCache" ExpansionMode="FullScreenOnly">
Anything I'm doing wrong?
EDIT 2: Thanks a lot for your answers you definitely pointed me in the right direction. I found a solution to my problem i binded my Pivot view's ItemsSource and from that i could in me view model add an ObservableCollection<string> then i could run this code again from my view model LstItems[PivotSelectedIndex].Data = new ObservableCollection<string>(items); where items is an string array. So in my String array i could make a string using the app resource with AppResources.YourResourceName.
You can set the items in code, In XAML have your normal ListPicker like this.
<toolkit:ListPicker x:Name="lstClubsPick"
FontSize="30"
Grid.Column="1"
VerticalAlignment="Center"
SelectionMode="Single"
HorizontalAlignment="Center"
CacheMode="BitmapCache"
SelectedIndex="{Binding KolleSelectedIndex, Mode=TwoWay}"
ExpansionMode="FullScreenOnly" />
Then in the C# code create a List and add the localized strings to it like this. And set the list as the ItemsSource of the ListPicker.
public MainPage()
{
InitializeComponent();
List<string> items = new List<string>();
items.Add(AppResources.OptionOne);
items.Add(AppResources.OptionTwo);
items.Add(AppResources.OptionThree);
items.Add(AppResources.OptionFour);
items.Add(AppResources.OptionFive);
lstClubsPick.ItemsSource = items;
}
you should be good to go. Hope it helps
I don't think it's a localization issue, but a problem with the ListPicker itself. I know by experience that setting ExpansionMode to FullScreen doesn't work when specifying the list items in XAML. Try removing the ExpansionMode property from the ListPicker declaration, does it work now?
If yes, I'm afraid the only option you've got is to declare the list of items in your viewmodel, e.g. as ObservableCollection<string>, and bind it like:
<toolkit:ListPicker ItemsSource="{Binding Items}" ...
In this case, ExpansionMode="FullScreen" works like a charm, don't ask me why...
If you really want to stick with the list of items declared in XAML code, you'll have to get rid of the ExpansionMode property somehow. In the past you could have used the ItemCountThreshold property: This one controls whether the picker opens in full screen mode (if it contains more items than specified as ItemCountThreshold) or not - set it to 0 to force full screen mode. Unfortunately, this property is not supported any more in current Toolkit versions, and the workarounds discussed in this similar question don't work for me either.
try this..there are two ways..u can do it only using xaml like following code..
<toolkit:ListPicker x:Name="listStatic" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Stretch" FullModeHeader="Choose the Mode">
<system:String>abc</system:String>
<system:String>abc</system:String>
<system:String>abc</system:String>
<system:String>abc</system:String>
<system:String>abc</system:String>
<system:String>abc</system:String>
</toolkit:ListPicker>
or you can use both xaml and c# like the following..
add this to your .cs file..
private List<string> SetData()
{
List<string> data = new List<string>();
data.Add("abc");
data.Add("abc");
data.Add("abc");
data.Add("abc");
data.Add("abc");
data.Add("abc");
data.Add("abc");
return data;
}
Add this to main method..
public MainPage()
{
InitializeComponent();
listDynamic.ItemsSource = SetData();
}
then add the following to the xaml file..
<toolkit:ListPicker x:Name="listDynamic" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Stretch" FullModeHeader="Choose the Mode">
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="6,12,6,12">
<Rectangle Fill="Green" Height="24" Width="24" />
<TextBlock Text="{Binding}" Margin="12,0,0,0" FontSize="{StaticResource PhoneFontSizeLarge}" />
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
this works great..hope this will help you..
Related
So here is my problem:
I want to access the items (and their properties), which are bound to a ListBox via a Bindable Collection, in a method of another class. (ShellViewModel)
More precise: I want to know which Items in this List are currently selected.
I'm using C#,Caliburn.Micro and the design pattern should be MVVM.
If the Button "Evaluate" is pressed, according to the selected ListBoxItems, different Methods get called.
So the XAML-Code in the ShellView is working fine, and also the "functional" code "works", but it is just working if I code directly in the xaml.cs-file. (big no,no)
Because I'm quite new to this topics, I've tried to create a new instance of the View for the access, but this will just give me control over the ListBox without "knowing" which Items are selected in the original instance.
Here is the general ListBox
<ListBox x:Name="MainListBox" ItemsSource="{Binding SCollection}"
Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="6" Grid.RowSpan="1"
SelectionMode="Multiple"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
MaxHeight="300" MinHeight="200" MaxWidth="340" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="0,5">
<StackPanel>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Padding="3,5,5,5" />
<TextBlock Text="{Binding Path=Info}" FontWeight="SemiBold" Padding="3,5,5,5" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="Evaluate" Background="Blue" Grid.Column="1" Grid.Row="7" MinWidth="80" Margin="5" Content="Test" Grid.ColumnSpan="1" />
So here are some questions:
Is there a similar solution like the binding of "SelectedItem" via xaml, which is bound to accessible variable, for multiple selected Items?(maybe I just missed something there?)
Is there a way to access the "original" instance of the ListBox(and therefore "live"-selected Items)?
To be clear:
Only problem, besides maybe other better solutions out there, is that, I want the called Method "Evaluate", which is bound to the button, have access to the great knowledge of which Items are selected in my ListBox.
I believe I understood your concern correctly. For the Evaluate method to have the knowledge of which Items has been selected, you can adopt the following strategy.
Add a boolean property in your Collection Type called IsSelected, which would help in tracking the items which are selected. For example,
public class Contact : PropertyChangedBase
{
public string Name { get; set; }
public string Info { get; set; }
public bool IsSelected { get; set; }
}
Now assuming your Collection is defined as following.
public ObservableCollection SCollection { get; set; } = new ObservableCollection();
You can filter the Selected items in Evaluate Method as following.
public void Evaluate()
{
var selected = SCollection.Where(x => x.IsSelected);
}
Update
You would need to Set the IsSelected Property to true during the selection in the List box. This can be done as following.
<ListBox x:Name="MainListBox" ItemsSource="{Binding SCollection}"
SelectionMode="Multiple"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
MaxHeight="300" MinHeight="200" MaxWidth="340" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="0,5">
<StackPanel>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Padding="3,5,5,5" />
<TextBlock Text="{Binding Path=Info}" FontWeight="SemiBold" Padding="3,5,5,5" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Example Screenshot
Does anyone know of the correct way to add multiple sections of text to one listview item when using Windows 10 universal apps in C#? Items.subitems doesn't seem to work. Say my two string I want to display in a single list item are stored in...
public class listContent
{
public string heading { get; set; }
public string subHeading { get; set; }
}
Would doing something similar to this work?
listContent listItem = new listContent();
listItem.heading = "HEADING";
listItem.subHeading = "subheading";
lsvTransactions.Items.Add(listItem);
Regards
Nathan
Best way is to DataBind to a custom DataTemplate. Considering you already have lsvTransactions name ListView. Here is what you should do.
Create a List of listContent in your .cs file showed below
public class MainPage : Page
{
public List<listContent> ContentList {get; set;}
.....
Add Items to this ContentList in your code like you did above.
After adding items add the following line to point to data source.
lsvTransactions.DataContext = ContentList;
Create a ListView like shown below with DataTemplate
<ListView x:Name="lsvTransactions" ItemsSource={Binding}>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding heading}"/>
<TextBlock Text="{Binding subheading}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As it was said maybe if you give us more info on your code, we can help better. I post you here a sample of a Listbox (which is similar to the listview) with the definition of the ItemTemplate for the elements I use and how to bind the items to the listbox and the fields in the items to the elements put in the Listbox.
<ListBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Path=MeasureUnits, Mode=OneWay}"
SelectedItem="{Binding Path=SelectedMeasureUnit, Mode=TwoWay}"
SelectionMode="Single" Margin="0"
IsSynchronizedWithCurrentItem="True" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<WrapPanel>
<TextBlock Text="{Binding Path=ID}" Style="{StaticResource idStyle}" />
<TextBlock Text="{Binding Path=Description}" Style="{StaticResource desStyle}"/>
</WrapPanel>
<WrapPanel>
<TextBlock Text="{Binding Path=DestinationUnitsInSource}" Style="{StaticResource numStyle}" />
<TextBlock Text="{Binding Path=SourceUnitsInDestination}" Style="{StaticResource numStyle}" />
</WrapPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In my XAML:
<ListView x:Name="listView">
In my C#:
listView.Items.Add(item);
Where Item is an object with multiple text elements.
If you post code I can be more specific.
I am trying to copy a WinForms application using WPF.
In my application I have a ComboBox that is filled with the titles of movies, to let me search the movies. Now that I'm porting it to WPF, I want to use the ComboBox to display the title and poster image of the movie.
I have already created the ComboBox and the two objects, but don't know how to populate the ComboBox at runtime, because the Add method doesn't let me add the two objects at one.
combobox.items.add()
Please help me find out how to fill the ComboBox with text and images at runtime.
update: this is the xaml code for the combobox
<ComboBox x:Name="busca_pelicula" HorizontalAlignment="Left" VerticalAlignment="Top" Width="334" Margin="147,93,0,0" IsEditable="True">
<ComboBox.Effect>
<DropShadowEffect/>
</ComboBox.Effect>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Center" Name="PeliText"/>
<Image HorizontalAlignment="Right" Height="50" VerticalAlignment="Center" Width="50"/>
</ComboBox>
and the code for fill the combobox with my data from my movie database is this
busca_pelicula.Items.clear();
using sql stuff to retrieve title and movie poster
BitmapImage ImagenPoster = new BitmapImage();
ImagenPoster.BeginInit();
ImagenPoster.UriSource = new Uri(wMediaPath+"Peli\\"+wNombrePoster);
ImagenPoster.EndInit();
busca_pelicula.Items.Add(? don't know what to put here)
Firstly you have to create a class similar to this:
public class Movie : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
public ImageSource Picture { get; set; }
}
Then in your xaml you have to change the combo as follow:
<ComboBox >
<ComboBox.ItemTemplate>
<ItemContainerTemplate>
<StackPanel>
<Image Source="{Binding Picture}"></Image>
<TextBlock ><Run Text="{Binding Name}"/></TextBlock>
</StackPanel>
</ItemContainerTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
this is the way to declare the wpf combobox with uge amount of data to let you "virtualize" the render
<ComboBox x:Name="busca_pelicula" HorizontalAlignment="Left" VerticalAlignment="Top" Width="334" Margin="147,93,0,0" IsEditable="True" Height="55" SelectionChanged="busca_pelicula_SelectionChanged" >
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.Effect>
<DropShadowEffect/>
</ComboBox.Effect>
<ComboBox.ItemTemplate>
<ItemContainerTemplate>
<StackPanel>
<TextBlock ><Run Text="{Binding Name}" /></TextBlock>
<Image Source="{Binding Picture}" Width="50" Height="50" HorizontalAlignment="Right"></Image>
</StackPanel>
</ItemContainerTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
now is working like a charm, the combobox only renders the 10 items that it is showing, hope that helps some one.
I have a ListView with SelectionMode=Multiple and two TextBoxes. One should display the top-most selected item, one should display the bottom most selected item. I am also working using the MVVM design pattern.
The issues are as follows:
"SelectedItems" is indexed from the first selection point - so the SelectedItems[0] can be the bottom-most selected item, which is undesirable. I want the top-most item to display in the top box and the bottom-most item to display in the bottom box.
I can't seem to reference SelectedItems[ SelectedItems.Count - 1] from the XAML in order to display the last selected item.
Here's a look at my current XAML:
<ListView x:Name="myListView" ItemsSource="{Binding MyList}"
SelectionMode="Multiple">
<TextBox x:Name="topTextBox" Grid.Column="1" Grid.Row="2"
Text="{Binding ElementName=myListView, Path=SelectedItems[0].ID}" />
<TextBox x:Name="bottomTextBox" Grid.Column="1" Grid.Row="3"
Text="{Binding ElementName=myListView, Path=SelectedItems[SelectedItems.Count-1].ID}" />
I'm not sure what the best approach to take is.
The solution I settled on is as follows:
I used the interactive namespace (Don't forget to reference the DLL) and the following XAML:
xmlns:interact="http://schemas.microsoft.com/expression/2010/interactivity"
<TextBox x:Name="startTextBox" Grid.Column="1" Grid.Row="2"
Text="{Binding LatestSelectedItem}" />
<ListView x:Name="myListView" ItemsSource="{Binding MyList}"
SelectionMode="Extended" >
<interact:Interaction.Triggers>
<interact:EventTrigger EventName="MouseUp"> <!-- Alternatively, OnSelectionChanged -->
<interact:InvokeCommandAction Command="{Binding MyListViewSelectionChangedCommand}"
CommandParameter="{Binding ElementName=myListView, Path=SelectedItems}" />
</interact:EventTrigger>
</interact:Interaction.Triggers>
</ListView>
Then I provided appropriate Properties in my ViewModel, along with the following command:
private void MyListView_SelectionChanged(object param)
{
IList selectedItems = (IList)param;
List<MyViewModel> myList = selectedItems.OfType<MyViewModel>().ToList();
if (myList.Count > 0)
{
myList.Sort(); // Implement comparator on MyViewModel
LatestSelectedItem = myList[myList.Count-1];
}
}
Works fine.
I have the following xaml:
<UserControl.Resources>
<sivm:Locator x:Key="viewModelLocator" ModelType="{x:Type ViewModels:RateVSConcentrationViewModel}"/>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Path="ViewModel" Source="{StaticResource viewModelLocator}"/>
</UserControl.DataContext>
...
<ComboBox Grid.Column="0" Grid.Row="1" Height="20" VerticalAlignment="Top" ItemsSource="{Binding Chambers}" > <!--SelectedItem="{Binding SelectedChamber}">-->
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ChamberName}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Chambers is an ObservableCollection of objects that contains a property called ChamberName which I want displayed in the combobox.
In the ViewModel I have the following code:
foreach (var chamber in chambers)
{
Chambers.Add(chamber);
}
OnPropertyChanged(() => Chambers);
But when this code executes the combobox is not updated. I have used this way to do a lot of databinding but I can't get this to work.
Can someone see what I am doing wrong here?
You may need to set the relativesource on your textblock, try modifying the binding on the Text property of your textblock to the following:
{Binding DataContext.ChamberName, RelativeSource={RelativeSource AncestorType=ComboBox}}
And as nit said above, always check for binding errors, they will put you on the right path.
You should adjust the property binding as follows:
<ComboBox ItemsSource="{Binding Path=ViewModel.Chambers, Source={StaticResource viewModelLocator}}" >
I got it to work doing this:
<ComboBox DisplayMemberPath="ChamberName" Grid.Column="0" Grid.Row="1" Height="20" VerticalAlignment="Top" ItemsSource="{Binding Chambers}"> <!--SelectedItem="{Binding SelectedChamber}">-->