cascading dropdown in wp8 - c#

I'm try to create cascading dropdown when i select first one it's working fine.On SelectionChanged i'm try to bind second drop down on code behind it's show the result fine.But Dropdown show empty.here is my code..
Location ld = new Location();
ld = categoryList.SelectedItem as Location;
string id = "0";
try
{
id = Convert.ToString(ld.id);
}
catch (Exception ex)
{ }
if (id != "0")
{
// lstSublocation.Visibility = Visibility.Visible;
var lst = _lstlocation.Where(z => z.id == id).Select(z => z.sub_location).ToList();
lstSublocation.ItemsSource = lst;
}
In lst show 2 items.
<toolkit:ListPicker x:Name="lstSublocation" Foreground="Black"
BorderThickness="2" SelectionMode="Single"
VerticalAlignment="Bottom" Margin="12,0,10,460" BorderBrush="LightGray" Height="68" >
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding name}" Margin="12 0 0 0" Foreground="Black"/>
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0 21 0 20">
<TextBlock Text="{Binding name}"
Foreground="Black"
/>
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
Here is front end code ..... :( 2 hours struggle with this code like wrestlemania fight... :)

Code should work (as posted), this is probably where the problem is
var lst = _lstlocation.Where(z => z.id == id).Select(z => z.sub_location).ToList();
lstSublocation.ItemsSource = lst;
Put a break point at lstSublocation.ItemsSource = lst; and check what lst is
Make sure it's actually a List<your_model> and that your_model has a Property of name not just a public variable.. like this
public class sample_model
{
public sample_model()
{
this.name = "default";
}
public string name { get; set; } // this is bindable
// public string name; // this is NOT bindable
}

Related

Combobox SelectedItem is not working in UWP

I have a Combobox with some items, i fill combobox this way:
var files = Directory.GetFiles(Constants.TranslationsPath);
var items = new ObservableCollection<Translation>();
using var db = new AlAnvarDBContext();
if (files.Count() > 0)
{
foreach (var file in files)
{
var id = Path.GetFileNameWithoutExtension(file);
var trans = db.Translations.Where(x => x.Link.Contains(id)).FirstOrDefault();
if (trans != null)
{
items.Add(trans);
}
}
cmbTranslators.ItemsSource = items;
cmbTranslators.SelectedItem = Settings.DefaultTranslation;
}
and xaml:
<ComboBox x:Name="cmbTranslators">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="table:Translation">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind Name}"/>
<TextBlock Text="-"/>
<TextBlock Text="{x:Bind Language}"/>
<TextBlock Text="-"/>
<TextBlock Text="{x:Bind Translator}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The problem is that the default item (SelectedItem) is not selected and i need to select default item in combobox.
cmbTranslators.SelectedItem = cmbTranslators.Items.Where(x=>((Translation)x).Id == Settings.DefaultTranslation.Id).FirstOrDefault();
Is it possible that the Settings.DefaultTranslation is not equal to any of the items in the item collection and that is why the assignment did not occur? Maybe you can add it to your collection Settings.DefaultTranslation like the first element and set cmbTranslators.SelectedIndex = 0

How do I pass a binded value from a listview into a function? C# UWP

I am working on a C# UWP assignment and I have a listview displaying information from a database. I want to show a list of orders, and each row has an orderID and a button to delete the order (which will delete it from the database). I though I could use a x:Name="orderid" and just pull that value in my function but it isn't recognizing it in the c# code.
.xaml.cs file includes:
Order o = new Order();
OrderList.ItemsSource = o.GetProducts(user);
.xaml (removed other columns for sake of example):
<RelativePanel Grid.Row="4" Grid.RowSpan="3" Grid.Column="0" Grid.ColumnSpan="7" HorizontalAlignment="Center">
<ListView Name="OrderList"
SelectionMode="Single"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.VerticalScrollMode="Enabled"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.IsHorizontalRailEnabled="True"
Margin="20">
<ListView.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="ID" Margin="8,0" Width="50" Foreground="DarkRed" />
<TextBlock Text="Date" Width="200" Foreground="DarkRed" />
<TextBlock Text="Delete" Width="50"/>
</StackPanel>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Order">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="orderid"
Text="{x:Bind OrderID}"
Width="50" />
<TextBlock Name="orderdate"
Text="{x:Bind OrderDate}"
Width="200" />
<Button Content="X" Click="Button_Click"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RelativePanel>
C# (Order Class - OrderID etc are all properties):
public ObservableCollection<Order> GetProducts(User user)
{
const string GetOrdersQuery = "select * from orders";
var orders = new ObservableCollection<Order>();
try
{
using (SqlConnection conn = new SqlConnection(user.ConnectionString))
{
conn.Open();
if (conn.State == System.Data.ConnectionState.Open)
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = GetOrdersQuery;
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var order = new Order();
order.OrderID = (int)reader["orderID"];
order.OrderDate = (DateTime)reader["orderDate"];
order.MethodOfDelivery = (string)reader["methodOfDelivery"];
order.DeliveryAddress = (reader["deliveryAddress"] as string);
order.MethodOfPayment = (string)reader["methodOfPayment"];
order.CardUsed = (reader["cardNumber"] as string);
order.Subtotal = (decimal)reader["subtotal"];
order.Discount = (decimal)reader["discountPercentage"];
order.Tax = (decimal)reader["tax"];
order.OrderTotal = (decimal)reader["orderTotal"];
order.CustID = (reader["custID"] as int?) ?? 0;
orders.Add(order);
}
}
}
}
}
return orders;
}
catch (Exception eSql)
{
Debug.WriteLine("Exception: " + eSql.Message);
}
return null;
}
and then I wanted to make a function in the xaml.cs file that would grab that row's orderID, and make a query to delete the order based on the id, but doing orderid.Text won't work here for some reason.
Any suggestions/help would be much appreciated!
If my code is a little all over the place it's because I'm fairly new to this!
One possible solution is to bind the "OrderId" to the "Tag" attribute in your Button element.
<Button Content="X" Click="Button_Click" Tag="{Binding Id}"/>
After the bind, in your Event handler for Click you call a method to remove it from database and from your ObservableCollection, something like:
private void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
var button = sender as Button;
_viewModel.DeleteOrder((int)button.Tag);
}
My DeleteOrder method is simple:
private ObservableCollection<Order> _orders;
public ObservableCollection<Order> Orders
{
get { return _orders; }
set { _orders = value; OnChange(); }
}
public void DeleteOrder(int id)
{
var order = Orders.FirstOrDefault(o => o.Id == id);
if (order != null)
{
Orders.Remove(order);
}
}

get checked items of listview using checkbox windows store app c#

I am developing one Windows store application. I have implemented one listview. listview contains image , textblock and checkbox controls. my listview gets the data from internet i have done xml parsing with listview and binded data to listview. i want to get all the data from listview where checkboxes are checked in listview.
my xaml code is:
<ListView Name="display" ItemsSource="{Binding}" SelectionMode="Single"
SelectionChanged="display_SelectionChanged"
ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.HorizontalScrollBarVisibility="Visible"
ItemContainerStyle="{StaticResource ListViewItemStyle12}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="stak2" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding Path=Image}" Width="450" Tapped="image_taped" />
<CheckBox Tag="{Binding Path=tag}" Visibility="{Binding Path=visichk}" Height="40" Name="addremove"
HorizontalAlignment="Center" Checked="add_checked" Unchecked="sub_checked" Opacity="0.5"
Background="White" VerticalAlignment="Top" Template="{StaticResource CheckboxImageTemplate}" >
</CheckBox>
<TextBlock Text="{Binding Image_code}" FontSize="25" Foreground="Gray" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
datasource for listview :
XDocument xmlDoc = XDocument.Parse(responseString);
var Categories = xmlDoc.Descendants("product").ToArray();
List<ProductData> displaylst = new List<ProductData>(); //ProductData is my Class.
foreach (var cat in Categories)
{
string prId = cat.Elements("id_products").Select(r => r.Value).FirstOrDefault();
List<string> Image = cat.Descendants("images").Elements("src").Attributes("largimage").Select(r => r.Value).ToList();
List<string> Image_code = cat.Descendants("images").Elements("src").Select(r => r.LastAttribute.Value).ToList();
int i = 0;
foreach (string img in Image)
{
displaylst.Add(new ProductData { Id = prId, Image = img, Image_code = Image_code[i] });
i++;
}
}
display.ItemsSource = displaylst;
Now on one button click i want to get the data of Product like prId,Image,Image_code where checkbox are checked from listview and put it into the simple list.
how can i did this please help me. thanks in advance.
First let's add a property to your ProductData class
public class ProductData
{
public string Id { get; set; }
public string Image { get; set; }
// I dont know exactly what's in this class
// ... more properties
// Add this one
public bool IsSelected { get; set; }
}
Now that we have a boolean IsSelected in our ProductData class we can know which are selected.
In the second foreach change this line
// Set IsSelected to false by default
displaylst.Add(new ProductData { IsSelected = false, Id = prId, Image = img, Image_code = Image_code[i] });
And bind the "IsChecked" property of your checkbox to IsSelected
<CheckBox IsChecked="{Binding Path=IsSelected}" Tag="{Binding Path=tag}" Visibility="{Binding Path=visichk}" Height="40" Name="addremove"
HorizontalAlignment="Center" Checked="add_checked" Unchecked="sub_checked" Opacity="0.5"
Background="White" VerticalAlignment="Top" Template="{StaticResource CheckboxImageTemplate}" >
With binding when you check one of the checkbox, the associed productData IsSelected property will become "true" automatically.
So now you just have to do a new list and select only ProductData where IsSelected is true:
List<ProductData> listOfSelectedProducts = (from product in displaylst
where product.IsSelected == true
select product).ToList();
Here you go you got a list of ProductData with only selected products.

binding data - inotifypropertychanged does not work

I have a listBox1 in which data are binding from the list. Then I want to when I select any item from listBox1 in listBox2 will binding data from another list.
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Teams teams = (Teams)listBox1.SelectedItems[0];
getH2hResults("//td[#class='hell']", teams.Team1, teams.Team2); // add elements to list
getH2hResults("//td[#class='dunkel']", teams.Team1, teams.Team2); // and here also
listBox2.ItemsSource = lists.h2hList;
}
On the first time this work, but for the twice time listBox2 doesn't displays new data.
public class Lists : BindableBase
{
public Lists()
{
_teamsList = new List<Teams>();
_h2hList = new List<H2H>();
}
private List<Teams> _teamsList;
public List<Teams> teamsList
{
get
{
return _teamsList;
}
set
{
if (value != _teamsList)
{
_teamsList = value;
RaisePropertyChanged("teamsList");
}
}
}
private List<H2H> _h2hList;
public List<H2H> h2hList
{
get
{
return _h2hList;
}
set
{
if (value != _h2hList)
{
_h2hList = value;
RaisePropertyChanged("h2hList");
}
}
}
}
And XAML
<ListBox Name="listBox1" Width="300" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding teamsList}" SelectionChanged="listBox1_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="#FF4273CD" Text="{Binding Team1, Mode=TwoWay}"></TextBlock>
<TextBlock Text=" vs " FontWeight="Bold"></TextBlock>
<TextBlock Foreground="#FF4273CD" Text="{Binding Team2, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="listBox2" Grid.Column="1" Width="300" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding h2hList}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding date, Mode=TwoWay}"></TextBlock>
<TextBlock Text="{Binding result, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
RaisePropertyChanged("teamList");
is Wrong your propery is named 'teamsList' with an S,
change to:
RaisePropertyChanged("teamsList");
It is the public property you bind to and notify changes of,
edit:
also change your binding:
ItemsSource="{Binding teamList}"
to
ItemsSource="{Binding teamsList}"
Edit 2:
listBox2.DataContext = xxx
Not itemsource = xxx
With the line (in listBox1_SelectionChanged)
listBox2.ItemsSource = lists.h2hList;
you are effectively removing the binding from the ItemsSource property of listBox2.
Instead, you should only update the h2hList property in your Lists class (which presumably happens in getH2hResults) and remove the above line from your code.
Note however that it is not sufficient to clear and re-fill that list. You need to set the h2hList property in order to get a property change notification raised:
var newList = new List<H2H>();
// fill newList before assigning to h2hList property
lists.h2hList = newList;
If you want to keep the list and just change its elements, you would need to use ObservableCollection<H2H> instead of List<H2H> as collection type. This would be the better approach anyway, as you would not have to care for when exactly you add elements to a newly created collection.

Databinding with a listbox

I have a bit of code that reads a json response from an HTTP server, it then parses this and inserts the data into a ListBox control.
The event I fire off when the download is complete is the following:
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser =
new DataContractJsonSerializer(typeof(ObservableCollection<UserLeaderboards>));
ObservableCollection<UserLeaderboards> users =
ser.ReadObject(e.Result) as ObservableCollection<UserLeaderboards>;
foreach (UserLeaderboards em in users)
{
int Fid = em.id;
string Fusername = em.username;
int Fscore = em.score;
lstbLeaders.Items.Add(Fid + Fusername + Fscore);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Now, when I do the items.add I presume it's just joining up the 3 variables and adding it to one column in the ListBox. This works fine and I see all 3 items joined up and displayed.
I want to separate this and make it look a bit nicer so I've created some XAML to try and bind the variables to textblocks. The following is just binding the username. I also have a public class that get/sets all 3 variables.
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0"
Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<DataTemplate>
<TextBlock Text="{Binding Source=Fusername}" />
</DataTemplate>
</ListBox>
When running the above I get nothing displayed at all. I have a feeling it's something simple?
Thanks.
To display a simple string your xaml should look like this:
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0"
Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
and you have to provide an object instead of a simple string if you want to split the properties to make it look nicer. If you just add Fid + Fusername + Fscore you will end up with a plain string.
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0"
Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Score}" />
</StackPanel>
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
You will need a view class:
public class UserView
{
public string Id {get;set;}
public string Name {get;set;}
public int Score {get;set;}
}
in your code behind:
var usersList = new List<UserView>();
foreach (UserLeaderboards em in users)
{
int Fid = em.id;
string Fusername = em.username;
int Fscore = em.score;
usersList.Add(new UserView { Id = Fid, Name = Fusername, Score = Fscore} );
}
lstbLeaders.ItemsSource = usersList;
Further notes:
Why not bind the ObservableCollection<UserLeaderboards> direcectly to the list box?
If there is no reason to convert to an other type skip the foreach part of the code and simply set lstbLeaders.ItemsSource = users;.
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
try
{
var ser = new DataContractJsonSerializer(
typeof(ObservableCollection<UserLeaderboards>));
var users = ser.ReadObject(e.Result)
as ObservableCollection<UserLeaderboards>;
lstbLeaders.ItemsSource = users;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Take look at the MVVM pattern. If you want to work with XAML you should know about this. It simplifies your work and creates cleaner code.
If you want to add edit functionality or data can change you may need to implement INotifyPropertyChanged on the View class.
You can use type inference which especially helps when working with cumbersome class names. var list = new ObservableCollection<SomeLongTypeName>() saves much typing and screen estate.
Hungarian notation makes me cringe ;)
I think you missed the ItemTemplate.
Try this
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0" Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Source=Fusername}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Categories

Resources