I've got a problem with ListBox. I'm trying to populate it with data from database, but the listbox doesn't show. I've looked through many similar questions, but didn't find any answer that would work for me :(
My code for ListBox:
<ListBox x:Name="OrdersListBox" Grid.Row="1" VerticalContentAlignment="Center" ItemTemplate="{StaticResource OrdersTemplate}">
</ListBox>
And for OrdersTemplate:
<DataTemplate x:Key="OrdersTemplate">
<StackPanel>
<DockPanel DockPanel.Dock="Left" DataContext="{StaticResource OrdersViewSource}">
<TextBlock Text="OrderID: " FontSize="18"/>
<TextBlock Text="{Binding OrderID}" FontSize="18"/>
</DockPanel>
</StackPanel>
</DataTemplate>
Code for Page:
public partial class Account : Page
{
Entities1 Context;
Customers Customer;
CollectionViewSource OrdersViewSource;
public Account(Entities1 Context, Customers Customer)
{
InitializeComponent();
this.Context = Context;
this.Customer = Customer;
this.OrdersViewSource = this.FindResource("OrdersViewSource") as CollectionViewSource;
DataContext = this;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Context.Orders.Load();
this.OrdersViewSource.Source = Context.Orders.Local.Where(o => o.CustomerName == Customer.CompanyName).Select(o => o);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Orders Order = new Orders
{
CustomerName = Customer.CompanyName
};
NewOrder NewOrder = new NewOrder(Context, Order);
this.NavigationService.Navigate(NewOrder);
}
}
I've got also this in Grid.Resources:
<CollectionViewSource x:Key="OrdersViewSource"/>
I'm pretty sure that binding works, 'cause when calling ListBox this way:
<ListBox x:Name="OrdersListBox" Grid.Row="1" VerticalContentAlignment="Center" ItemTemplate="{StaticResource OrdersTemplate}">
<DockPanel/>
</ListBox>
it shows the first OrderID element.
Why can't I see any ListBox when running my app?
Ok what you have done is that you bound your ItemTemplate to the resource you wanted. Which should be ItemsSource instead.
When you added an item manually the list tried to render your item using the template that you provided which is your actual data.
You might want to do something like this:
<ListBox x:Name="OrdersListBox" Grid.Row="1"
VerticalContentAlignment="Center"
ItemTemplate="{StaticResource OrdersTemplate}"
ItemsSource="{Binding Source={StaticResource OrdersViewSource}}">
</ListBox>
And then remove the data binding on the template like this:
<DataTemplate x:Key="OrdersTemplate">
<StackPanel>
<DockPanel DockPanel.Dock="Left">
<TextBlock Text="OrderID: " FontSize="18"/>
<TextBlock Text="{Binding OrderID}" FontSize="18"/>
</DockPanel>
</StackPanel>
</DataTemplate>
I'm not sure of this works because I don't know that if the data in OrdersViewSource is the actual items that you want to show in the list but you get the idea.
You need an array of items assigned to the ItemsSource property of the list.
Related
very new to C# WPF/WIN UI. My combobox displays my collection perfectly. But now when I want to do something with what the user selected I can't find the correct syntax in my 'SelectionChanged' event handler. I want to get the 'Market_ID' somehow. (FYI, I am not using MVVM yet as I don't understand how to implement, but I will learn. (really liking c#))
<ComboBox x:Name="cmbMarketID" PlaceholderText="Select Market ID" Width="500" Margin="5,5,0,0" RelativePanel.RightOf="border1" RelativePanel.Below="cmbState" ItemsSource="{x:Bind marketIdent}" SelectionChanged="cmbMarketID_SelectionChanged" SelectedItem="{Binding Market_ID}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="cmbo_market_ID" Text="{Binding Market_ID}" Width="15" TextAlignment="Right"/>
<TextBlock Text="{Binding Product}" Width="145" Margin="10,0,10,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding Company}" Width="70" Margin="10,0,10,0"/>
<TextBlock Text="{Binding System}" Margin="10,0,10,0"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Here is the event handler: (I used a simple string first, and that worked, but now I need to use a typed-collection)
private void cmbMarketID_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cmbMarketID.SelectedIndex == -1)
{
// Do not execute event
}
else
{
//string mktid = cmbMarketID.SelectedItem.ToString().Substring(0, 2).TrimEnd();
//string mktid = cmbMarketID.SelectedItem;
int mktid = (int)cmbMarketID.SelectedItem(); <-------what should the correct syntax be here?
//v_metric_mktid = mktid;
}
}
Cast the SelectedItem property to your type.
For example, if marketIdent is an IEnumerable<YourClass>:
var item = cmbMarketID.SelectedItem as YourClass;
Or if marketIdent is an IEnumerable<int>:
if (mbMarketID.SelectedItem != null)
{
var mktid = (int)mbMarketID.SelectedItem;
}
I'm loading data from an xml file into a listbox . Here is my xaml
<ListBox x:Name="lstSearchCategory" FontFamily="Arial Black"
VerticalAlignment="Center" Margin="25,69,19,10" Height="264">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel >
<Image Source="{Binding Image}" Height="100" Width="100"
HorizontalAlignment="Left"></Image>
<TextBlock HorizontalAlignment="Right" Text="{Binding Name}"
FontSize="30" Foreground="Black" Margin="140,-100,0,0"/>
<TextBlock Text="{Binding Category}" FontSize="24"
Foreground="Black" Margin="10,-10,0,0"/>
<TextBlock Text="{Binding Price}" HorizontalAlignment="Right"
Foreground="Red" Margin="300,-25,0,16"/>
<Rectangle Width="500" Fill="Black" Height="0.5"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is working fine. Now I want that when I select any listbox item, I get its respective values i.e image, price, category etc. How can i do this ? Help
You need to get the selected item in a ListBox Event and get the DataTemplate from the ListBox (as seen on MSDN):
private void lstEvents_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBoxItem lbi = (lstEvents.ItemContainerGenerator.ContainerFromIndex(lstEvents.SelectedIndex)) as ListBoxItem;
ContentPresenter cp = GetFrameworkElementByName<ContentPresenter>(lbi);
DataTemplate dt = lstEvents.ItemTemplate;
Label l = (dt.FindName("lblEventId", cp)) as Label;
MessageBox.Show(l.Content.ToString());
}
You need generate Tap = "lstSearchCategory_Tap" in your XAML file and below code in .cs file
private void lstSearchCategory_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
try
{
ListBox ListBoxSelecteditem = (ListBox)sender;
YourModel model = (YourModel)ListBoxSelecteditem.SelectedItem;
string name = model.Name;
string cat = model.Category;
.......
string ControlName = ((System.Windows.FrameworkElement)
(((System.Windows.RoutedEventArgs)(e)).OriginalSource)).Name;
if (ControlName.ToLower() != "name".ToLower())
{
}
}
catch (Exception ex)
{ }
}
try this
<ListBox Tap="lstSearchCategory_Tap" x:Name="lstSearchCategory">
and than on tap event add this
var selected = (classname)lstSearchCategory.SelectedValue;
MessegeBox.Show(selected.Name + selected.Price);
here class-name is name of class where you are binding the name, price etc values
If you fill your ListBox via binding, you should have some property lile SelectedItem in your view model. So the currently selected item should always be stored in the viewmodel for easy access. Just add a binding to SelectedItem in your viewmodel and every thing should work.
I have a web browser which is storing all the visited websites. There is just one issue, I would like it for the user to click on one of the records and then it should open in the webbrowser.
Once the user has navigated to a page, this method is called with the url:
public List<String> urls;
public string selectedURL;
public MainPage()
{
InitializeComponent();
listBox.DataContext = urls;
}
private void getHistory(string url)
{
urls.Add(url);
listBox.DataContext = null;
listBox.DataContext = urls;
}
private void listBoxtrend_Tap(object sender, GestureEventArgs e)
{
selectedURL = "";
var selected = listBox.SelectedValue as Item;
selectedText = selected.ItemString;
MessageBox.Show(selectedURL);
browserSearch(selectedURL);
}
This is then displayed into a textblock on a pivot page:
<phone:Pivot Margin="0,0,0,0">
<phone:PivotItem Header="" Margin="0,-104,0,0">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="72"/>
<RowDefinition Height="696"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#FF5E667B" >
</Grid>
</phone:PivotItem>
<phone:PivotItem Margin="0,-104,0,0" Header="">
<Grid>
<ListBox ItemsSource="{Binding Item}" Foreground="RoyalBlue" Name="listBox"
TabIndex="10" Tap="listBox_Tap" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" FontSize="26" HorizontalAlignment="Left"
x:Name="txtHistory" Text="{Binding ItemString}"
VerticalAlignment="Top" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</phone:PivotItem>
</phone:Pivot>
I have tried to put a click event, but there is one way to tell which record is being clicked. Is there a way to use the SelectionChanged event handler. And is there a better way to store this data, maybe in a array or list which then can be saved to IsolatedStorage.
Thank you in advance :)
If you need any more details please comment and I will be happy to explain in further detail :)
It's better if you would have the data you're going to display within a Listbox, I mean the Url's. So that you could easily get whatever the data you want from the clicked item. Make sure that you bind the source for your Listbox.
your xaml:
<ListBox ItemsSource="{Binding Item}" Foreground="RoyalBlue"
Height="395" HorizontalAlignment="Center"
Margin="12,111,0,0" Name="listBox"
VerticalAlignment="Top" Width="438"
TabIndex="10" Tap="listBox_Tap" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" FontSize="26" HorizontalAlignment="Left"
x:Name="txtHistory" Text="{Binding ItemString}"
VerticalAlignment="Top" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And then from your tap event handler of the Listbox
private async void listBoxtrend_Tap(object sender, GestureEventArgs e)
{
selectedText = "";
var selected = listBox.SelectedValue as Item;
selectedText = selected.ItemString;
MessageBox.Show(selectedText);
await Launcher.LaunchUriAsync(new Uri("give the url"));//here should be the selectedText
}
These can be referable for more:
Getting selected value of listbox windows phone 7
LIstbox Selected Item content to textblock
Hope it helps!
I'm trying to create an ItemTemplate for a ListBox programmatically but it doesn't work. I know in XAML I can have something like:
<ListBox x:Name="listbox" BorderThickness="0" Margin="6" Height="400">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="0" Background="Red" Foreground="White" FontSize="18" Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But when I'm trying to have the above result programmatically I face a problem which is binding the TextBox.TextProperty:
var textblock = new FrameworkElementFactory(typeof(TextBlock));
// Setting some properties
textblock.SetValue(TextBlock.TextProperty, ??);
var template = new ControlTemplate(typeof(ListBoxItem));
template.VisualTree = textblock;
Please help me on this issue. I couldn't find anything on the web about it.
Thanks in advance.
Try use dot . in Binding, this is the equivalent of {Binding}.
Example:
XAML
<Window x:Class="MyNamespace.MainWindow"
...
Loaded="Window_Loaded">
<ListBox Name="MyListBox" ... />
</Window>
Code-behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
textBlockFactory.SetValue(TextBlock.TextProperty, new Binding(".")); // Here
textBlockFactory.SetValue(TextBlock.BackgroundProperty, Brushes.Red);
textBlockFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Wheat);
textBlockFactory.SetValue(TextBlock.FontSizeProperty, 18.0);
var template = new DataTemplate();
template.VisualTree = textBlockFactory;
MyListBox.ItemTemplate = template;
}
}
Try this, by binding the "listbox" with ItemsSource and specify the datatemplate below like if you want to bind name then just write {Binding Name}
<ListBox x:Name="listbox" BorderThickness="0" Margin="6" Height="400" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="0" Background="Red" Foreground="White" FontSize="18" Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have a listbox in WPF databinded to a observablecollection
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding ShopList}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Grid.Row="1"
Grid.ColumnSpan="2" KeyDown="ListBox_KeyDown" KeyUp="ListBox_KeyUp"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17" >
<!--Replace rectangle with image-->
<Rectangle Height="50" Width="50" Stroke="Black" StrokeThickness="6" Margin="12,0,9,0"/>
<StackPanel Width="Auto">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding Quantity}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I then have a filter method I want called
private void ShopItemDay_Filter(object sender, FilterEventArgs e)
{
var item = e.Item as ShopItem;
e.Accepted = item.Day == 1;
}
But I cant find any properties on the Listbox to use a filter method like done here http://www.galasoft.ch/mydotnet/articles/article-2007081301.aspx
You need to create a 'view' on your collection. See the documentation for CollectionView.Filter. The framework will create a default view for all bound collections. You can add a filter as follows:
ICollectionView _customerView = CollectionViewSource.GetDefaultView(customers);
_customerView.Filter = CustomerFilter
private bool CustomerFilter(object item)
{
Customer customer = item as Customer;
return customer.Name.Contains( _filterString );
}
(From this tutorial);
As you can see in the article you linked to, the filter is not a property of the Control. It is a property of the CollectionViewSource which is a kind of wrapper around the collection. This wrapper allows for sorting, grouping and filtering.