I have a CartPage in WindowsPhone App. It shows Items in cart with their selected quantities.
I use a ListPicker to change the quantity. Now I have two questions,
How to set the default Quantity in ListPicker (I am getting the Quantity of product from localstorage).
When I select the quantity from ListPicker, How to save it into variable?
<Grid.Resources>
<DataTemplate x:Name="PickerFullModeItemTemplate">
<StackPanel Orientation="Horizontal" Margin="16 21 0 20" >
<TextBlock Name="TextQuantity" Text="{Binding Quantity}" Margin="16 0 0 0" FontSize="43" FontFamily="{StaticResource PhoneFontFamilyLight}"/>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<toolkit:ListPicker toolkit:TiltEffect.IsTiltEnabled="True" Name="QuantityBox" Margin="264,91,142,36" Background="#FFA05E6A" FullModeItemTemplate="{StaticResource PickerFullModeItemTemplate}" BorderBrush="#FF8D7373" Foreground="#FF310836" FontSize="20" SelectionChanged="QuantityBox_SelectionChanged" MouseEnter="QuantityBox_MouseEnter" BorderThickness="1"/>
public class ListQuantityClass
{
public int Quantity { get; set; }
}
List<ListQuantityClass> QuantitySource = new List<ListQuantityClass>();
for (int i = 1; i <= 20; i++)
{
QuantitySource.Add(new ListQuantityClass() { Quantity = i });
}
Custom.QuantityBox.ItemsSource = QuantitySource;
Both the below lines are giving me error:
Custom.QuantityBox.SelectedItem = cart.ProductQuantity;
singletonInstance.QuantityChanged = int.Parse(QuantityBox.SelectedItem.ToString());
Actually Its obvious QuantityBox.SelectedItem WONT WORk because ListPicker is Databdound to QuantitySource list. What to use instead of QuantityBox.SelectedItem?
Since this is a two part question I will split it up into two sections.
How to set the default Quantity in ListPicker (I am getting the
Quantity of product from localstorage).
You can set the SelectedItem only to an item in the ItemSource. Using your example,
public partial class MainPage : PhoneApplicationPage
{
List<ListQuantityClass> QuantitySource = new List<ListQuantityClass>();
// Constructor
public MainPage()
{
InitializeComponent();
for (int i = 1; i <= 20; i++)
{
QuantitySource.Add(new ListQuantityClass() { Quantity = i });
}
my_listpicker.ItemsSource = QuantitySource;
// setting default value to 3
my_listpicker.SelectedItem = QuantitySource[2];
// fancy search and set
// my_SetSelectedItemBasedOnQuantity(my_listpicker, 4); // this will set it to 4
}
}
When I select the quantity from ListPicker, How to save it into
variable?
This is a much more involved problem. You can loop through the Items in the ItemSource and check to see if it equals the SelectedItem and saved it that way. But I much prefer if you use an event, like so.
private void my_listpicker_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
var listpicker = sender as ListPicker;
if (listpicker != null)
{
var selected_item = listpicker.SelectedItem as ListQuantityClass;
int quantity = selected_item.Quantity;
// TODO: Save the value in quantity to a file or send it to a webservice
}
}
catch (Exception ex)
{
string error_message = ex.Message;
}
}
XAML
<Grid.Resources>
<DataTemplate x:Name="PickerItemTemplate">
<TextBlock Text="{Binding Quantity}" FontSize="43"/>
</DataTemplate>
<DataTemplate x:Name="PickerFullModeItemTemplate">
<TextBlock Text="{Binding Quantity}" Margin="16 0 0 0" FontSize="43"/>
</DataTemplate>
</Grid.Resources>
<toolkit:ListPicker Header="my list picker demo" x:Name="my_listpicker" ItemTemplate="{StaticResource PickerItemTemplate}" FullModeItemTemplate="{StaticResource PickerFullModeItemTemplate}" SelectionChanged="my_listpicker_SelectionChanged" MaxHeight="300"/>
Function to set SelectedItem based on Quantity
private void my_SetSelectedItemBasedOnQuantity(ListPicker lp, int quantity)
{
// first search for quantity if a match is found set it
try
{
foreach (ListQuantityClass lqc in lp.ItemsSource)
{
// match found
if (lqc.Quantity == quantity)
{
lp.SelectedItem = lqc;
}
}
}
catch (Exception ex)
{
string error = ex.Message;
}
}
I think you cannot use SelectedItem to set the selected item.You should set the SelectedIndex property instead. SelectedItem is used to get the selected item.Although the docs say that it can be used to set the selected item,I have never seen any practical implementation of the same.
Related
I'm trying to use a ListBox to choose an entry and then display a picture belonging to this selected entry. But just at the beginning I got my first problem: filling the ListBox with binding is working, but if I click on one line in my running program, it doesn't select the line. I can just see the highlighted hover effect, but not select a line. Any ideas what my mistake could be?
This is my XAML:
<ListBox x:Name="entrySelection" ItemsSource="{Binding Path=entryItems}" HorizontalAlignment="Left" Height="335" Margin="428,349,0,0" VerticalAlignment="Top" Width="540" FontSize="24"/>
And in MainWindow.xaml.cs I'm filling the ListBox with entries:
private void fillEntrySelectionListBox()
{
//Fill listBox with entries for active user
DataContext = this;
entryItems = new ObservableCollection<ComboBoxItem>();
foreach (HistoryEntry h in activeUser.History)
{
var cbItem = new ComboBoxItem();
cbItem.Content = h.toString();
entryItems.Add(cbItem);
}
this.entrySelection.ItemsSource = entryItems;
labelEntrySelection.Text = "Einträge für: " + activeUser.Id;
//show image matching the selected entry
if (activeUser.History != null)
{
int index = entrySelection.SelectedIndex;
if (index != -1 && index < activeUser.History.Count)
{
this.entryImage.Source = activeUser.History[index].Image;
}
}
}
So I can see my ListBox correctly filled, but not select anything - so I can't go on with loading the picture matching the selected entry.
I'm still quite new to programming, so any help would be great :)
EDIT: If someone takes a look at this thread later: here's the - quite obvious -solution
XAML now looks like this
<ListBox x:Name="entrySelection" ItemsSource="{Binding Path=entryItems}" HorizontalAlignment="Left" Height="335" Margin="428,349,0,0" VerticalAlignment="Top" Width="540" FontFamily="Siemens sans" FontSize="24">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code behind to fill it:
//Fill listbox with entries for selected user
DataContext = this;
entryItems = new ObservableCollection<DataItem>();
foreach (HistoryEntry h in selectedUser.History)
{
var lbItem = new DataItem(h.toString());
entryItems.Add(lbItem);
}
this.entrySelection.ItemsSource = entryItems;
labelEntrySelection.Text = "Einträge für: " + selectedUser.Id;
And new Class DataItem:
class DataItem
{
private String text;
public DataItem(String s)
{
text = s;
}
public String Text
{
get
{
return text;
}
}
}
You are filling it with ComboBoxItem, which is not relevant to the ListBox, and also wrong by definition.
You need to have the ObservableCollection filled with data items.
Meaning, make a class that contains the data you want to store, and the ListBox will generate a ListBoxItem automatically per data item.
http://www.wpf-tutorial.com/list-controls/listbox-control/
Iam new to implementing SQLITE DB & windows phone 8 app development...
Implemeted following startegy to retreive data to listbox which contains three other controls..
here is my XAML code..
<ListBox Height="Auto" Name="TaskListBox" Margin="5,61,-1,298">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Red" Height="480" Width="200">
<TextBlock Text="{Binding status }" Name="team1Name" Width="120" ></TextBlock>
<TextBlock Text="{Binding CreationDate }" Name="team3Name" Foreground="White" Width="120" HorizontalAlignment="Center"></TextBlock>
<HyperlinkButton Content="{Binding Merid_FK }" Name="team2Name" Foreground="White"/>
<TextBlock Text="{Binding status}" Name="venue" Foreground="White" Height="67" Width="78"></TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and my code behind
private void Insert_Click(object sender, RoutedEventArgs e)
{
using (var db = new SQLiteConnection(DB_PATH))
{
db.RunInTransaction(() =>
{
db.Insert(new tasks() { Merid_FK = 126745, status = "Y", CreationDate = DateTime.Now });
db.Insert(new tasks() { Merid_FK = 1289906, status = "N", CreationDate = DateTime.Now });
});
}
private void Retrieve_Click(object sender, RoutedEventArgs e)
{
List<tasks> listmerchant = dbConn.Query<tasks>("SELECT * from tasks where status='" + "Y" + "'").ToList<tasks>();
TaskListBox.ItemsSource = listmerchant;
}
my tasks class
public sealed class tasks
{
//[PrimaryKey,AutoIncrement]
public int Merid_FK { set; get; }
public string status { set; get; }
public DateTime CreationDate { set; get; }
public override string ToString()
{
return Merid_FK + ">> " + status + ">> " + CreationDate.ToShortDateString() ;
}
}
my problem is ,iam getting output as "16757 >> status1 >> 2012-12-20 12:20" on UI(in list box place.. not at the controls in data template).. its simply returning method placed in class tasks..please tell me how to bind data to controls placed inside the lsitbox.
i already followed lot of similar questions in stack over flow,..
Slect data from SQLite
bind data to list box
bind data dynamically
please keep height and width of listbox and controls inside listbox to "Auto" in xaml.if you used any border control..make sure width and height are set to "Auto"
Height="Auto" Width="Auto"
please check this and revert back with error picture..
I'm developing windows phone 8 application.
I'm using ListPicker option.
My Listpicker code
<toolkit:ListPicker x:Name="LPfilter" Foreground="White" BorderThickness="0" Margin="300,0,0,0" Height="80" Width="50" Visibility="Visible">
<toolkit:ListPicker.Background>
<ImageBrush ImageSource="/Assets/Images/filters.png"/>
</toolkit:ListPicker.Background>
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}" Visibility="Collapsed" Foreground="Red"/>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<TextBlock Tap="TextBlock_Tap">
<Run Text="{Binding name}"/>
</TextBlock>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
values bind to listpicker using webservice (json format).
Json result comes like this
[
-{
id: "9",
name: "Pizza",
root_id: "4",
level: "1",
},
-{
id: "10",
name: "Fine Dinind",
root_id: "4",
level: "1",
},
-{
id: "11",
name: "Fast Food",
root_id: "4",
level: "1",
},
....
]
c# code for bind values
public void businesscatbind()
{
string bus_caturl = "http://xxxxx.com/Service/filterquery.php?rootid=" + bus_catval;
WebClient bus_catwc = new WebClient();
bus_catwc.DownloadStringAsync(new Uri(bus_caturl), UriKind.Relative);
bus_catwc.DownloadStringCompleted += bus_catwc_DownloadStringCompleted;
}
void bus_catwc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var bus_catdata = e.Result;
var bus_catvalue = JsonConvert.DeserializeObject<List<bus_catbinddata>>(bus_catdata);
LPfilter.ItemsSource = bus_catvalue;
}
Problem occur in this event
private void TextBlock_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
bus_catbinddata elements = LPfilter.SelectedItem as bus_catbinddata;
int val = LPfilter.SelectedIndex;
filterid = int.Parse(elements.id);
MessageBox.Show(filterid.ToString());
}
My problem
First time i click pizza it's show the value = Id value 9 in msgbox
next i click Fine Dining it's show the value = Id value 9 in msgbox
next i click Fast Food it's show the value =10 in msgbox (10 Is the idvalue of FineDining)
next i click Italian it's show the value = 11 in msgbox (11 is the Idvalue of Fastfood)
previews selected item value is show in alert
Output
How to solve this issue.
Use Listpicker SelectionChanged event instead
<toolkit:ListPicker x:Name="LPfilter" Foreground="White" BorderThickness="0" Margin="300,0,0,0" Height="80" Width="50" Visibility="Visible" SelectionChanged="listPicker_SelectionChanged>
in Xaml page
<toolkit:ListPicker x:Name="listPicker" Foreground="White" BorderThickness="0" Margin="300,0,0,0" Height="80" Width="50" Visibility="Visible" SelectionChanged="listPicker_SelectionChanged" >
<toolkit:ListPicker.Background>
<ImageBrush ImageSource="/Assets/Images/filters.png"/>
</toolkit:ListPicker.Background>
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}" Visibility="Collapsed" Foreground="Red"/>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<TextBlock Tap="TextBlock_Tap">
<Run Text="{Binding name}"/>
</TextBlock>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
In .cs File
void listPicker_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
if (this.listPicker.SelectedItems != null && this.listPicker.SelectionMode == SelectionMode.Multiple)
{
for (int i = 0; i < this.listPicker.SelectedItems.Count; i++)
{
string str = ((Items)(this.listPicker.SelectedItems[i])).Name;
if (i == 0)
{
MessageBox.Show("Selected Item(s) is " + str);
}
else
{
//Some Code
}
}
}
else if (this.listPicker.SelectionMode == SelectionMode.Single)
{
MessageBox.Show("Selected Item is " + ((Items)this.listPicker.SelectedItem).Name);
}
}
It seems that the "TextBlock_Tap" event fires up before the "ListPicker" changes its selection.
You can try to use the "SelectionChanged" event of the ListPicker - although it seems that you are not using it because you might want to select the same option twice. In that case, you can add a dummy item to the top of your list saying something like "Select Item" and in the "SelectionChanged" event in the end set the selected item of list picker to your dummy item.
EDIT:
In this method -
void bus_catwc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var bus_catdata = e.Result;
var bus_catvalue = JsonConvert.DeserializeObject<List<bus_catbinddata>>(bus_catdata);
LPfilter.ItemsSource = bus_catvalue;
}
add a new "bus_catbinddata" to the "var bus_catvalue" - it is a list - insert your dummy itme at index 0. then in selection changed event of list picker, add a condition if(ListPicker.SelectedIndex > 0) and only if this condition is true, the code will execute.
I haven't tried this specifically with ListPicker's full mode item template, but you can try to get corresponding model for tapped TextBlock from DataContext :
private void TextBlock_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
TextBlock textBlock = (TextBlock)sender;
bus_catbinddata elements = textBlock.DataContext as bus_catbinddata;
filterid = int.Parse(elements.id);
MessageBox.Show(filterid.ToString());
}
I cannot bind my sample data to textblocks in stackpanel, which I defined in resources. I think that I use style in wrong way, because I receive toString() method instead of class binded fields.
That's my resources with defined style:
<UserControl.Resources>
<ItemsPanelTemplate x:Key="VirtualizingStackPanelTemplate">
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<ListView x:Key="ListBoxTemplate" HorizontalAlignment="Left" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ListBoxItem Background="DarkOrchid" Margin="1,1, 5,5" Height="400" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch">-->
<StackPanel>
<TextBlock FontSize="30" Text="{Binding Title}"/>
<TextBlock FontSize="20" Text="{Binding Desc}"/>
</StackPanel>
<!--</ListBoxItem>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl.Resources>
Here is my method in which i add listview programatically:
long rowCount = ContentGridFullView.RowDefinitions.LongCount();
if (rowCount > 8) return;
var c1 = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
ContentGridFullView.RowDefinitions.Add(c1);
rowCount = ContentGridFullView.RowDefinitions.LongCount();
TextBlock tb = new TextBlock {Text = "TEXTBLOCK ITEM = " + (rowCount - 1), FontSize = 40};
Viewbox vb = new Viewbox { Child = tb };
if (rowCount > 8) return;
Grid.SetRow(vb, Convert.ToInt32(rowCount-1));
Grid.SetColumn(vb, 1);
ListView lb = new ListView();
lb.Style = Resources["ListBoxTemplate"] as Style;
lb.ItemsPanel = (ItemsPanelTemplate) Resources["VirtualizingStackPanelTemplate"];
var products = new ObservableCollection<Product>() { new Product("ASDASDSADAS", "VCBVCBVCBVCBC"), new Product("ASDASDSADAS", "VCBVCBVCBVCBC"), new Product("ASDASDSADAS", "VCBVCBVCBVCBC"), new Product("ASDASDSADAS", "VCBVCBVCBVCBC") };
lb.ItemsSource = products;
ContentGridFullView.Children.Add(lb);
ContentGridFullView.Children.Add(vb);
Grid.SetRow(lb, Convert.ToInt32(rowCount - 1));
Grid.SetColumn(lb, 2);
And my short class that I want to bind:
public class Product
{
public string Title { get; set; }
public string Desc { get; set; }
public Product(string title, string desc)
{
Title = title;
Desc = desc;
}
public override string ToString()
{
return "I see that message instead of Title and Desc";
}
}
Can someone tell me what's wrong with this code? Thank you.
Create your Observable collection as a property (getter/setter):
ObservableCollection<Product> _products;
public ObservableCollection<Product> products
{
get{return _products;}
set
{
_products=value;
PropertyChanged("products");
}
}
The property changed event will be need to indicate that the collection has changed,its needed when your using ObservableCollection. You'll need to read more about it.You can add items to the products collection by using :
products.Add(Product_object)
And your xaml code will have the itemsSource as follows:
<ListView x:Key="ListBoxTemplate" HorizontalAlignment="Left" ScrollViewer.HorizontalScrollBarVisibility="Visible" ItemsSource="{Binding products}">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ListBoxItem Background="DarkOrchid" Margin="1,1, 5,5" Height="400" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch">-->
<StackPanel>
<TextBlock FontSize="30" Text="{Binding Title}"/>
<TextBlock FontSize="20" Text="{Binding Desc}"/>
</StackPanel>
<!--</ListBoxItem>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The following statement is important in your xaml code so that your xaml code will know where to look for the data.
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=x}
First try and create a static list and check if data is getting initialized properly and then you can try creating listviews dynamically. But the code above will be the same thing you will have to do create dynamic listviews.
I am working on a WPF where I need to dynamically generate Checkboxes 16 times.
XAML:
<Checkboxes Height="14" Command="{Binding CheckboxesGen}" Margin="0" Name="checkBox1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" />
Using above way, It will be inefficient if I write down this Checkboxes 16 times and have individual Button Click Command for them. I would ideally want to generate them 16 times and have one common method in my viewmodel class as follows:
private ICommand mCheckboxesGen;
public ICommand CheckboxesGen
{
get
{
if (mCheckboxesGen== null)
mCheckboxesGen= new DelegateCommand(new Action(mCheckboxesGenExecuted), new Func<bool>(mCheckboxesGenCanExecute));
return mCheckboxesGen;
}
set
{
mCheckboxesGen= value;
}
}
public bool mCheckboxesGenCanExecute()
{
return true;
}
public void mCheckboxesGenExecuted(some INDEX parameter which gives me selected Checkboxes )
{
// Have a common method here which performs operation on each Checkboxes click based on INDEX which determines which Checkboxes I have selected
}
I had faced the same situation in my C++ app. I had done it in my C++ app as follows:
for(int j = 0; j < 16; j ++)
{
m_buttonActiveChannels[j] = new ToggleButton();
addAndMakeVisible(m_buttonActiveChannels[j]);
m_buttonActiveChannels[j]->addButtonListener(this);
}
//Checking which Checkboxes is clicked
unsigned bit = 0x8000;
for(int i = 15; i >= 0; i--)
{
if(0 != (value & bit)) //Value has some hardcoded data
{
m_buttonActiveChannels[i]->setToggleState(true);
}
else
{
m_buttonActiveChannels[i]->setToggleState(false);
}
bit >>= 1;
}
Hence using this generates it 16 times and has one method which performs operation based on index i.
Using a similar approach or any other approach, How can I achieve it in my wpf app? :)
Please help :)
How about something like this?
<ItemsControl ItemsSource="{Binding CollectionOfObjectsThatRepresentYourCheckBox}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Checkbox Content="{Binding DisplayText }" Checked="{Binding Checked}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
you would need to populate your collection on objects on load or when a command was executed, then you could react to items being checked in the model that you create for it..
public class CheckBoxClass
{
public int Index {get; set;}
public string DisplayText {get; set}
private bool _checked;
public bool Checked
{
get { return _checked;}
set {
_checked = value
doSomethingWhenChecked();
}
}
ObservableCollection<CheckBoxClass> CollectionOfObjectsThatRepresentYourCheckBox = SomeMethodThatPopulatesIt();
this is a much cleaner way to do this and instead of generating the controls you will be just binding to a list of your objects that will be represented by a check box.
Define a viewmodel for the checkboxes, this class will have an Index property and the command implementation based on it. Add an ObservableCollection of checkboxes viewmodels to your current viewmodel. In the view add an ItemsControl bound to this collection with a proper ItemTemplate. You can now add as many checkboxes as you want dynamically in the viewmodel.