What should I do to get the values of a listbox item in wpf c#? - listbox

I have a few images with some text, I need to get the image path with the relevant text in a listbox.
Browsing google I came across this sample class,
public class Img
{
public Img(string value, Image img) { Str = value; Image = img; }
public string Str { get; set; }
public Image Image { get; set; }
}
<ListBox x:Name="lstBox">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Img}">
<StackPanel>
<TextBlock Margin="3" Text="{Binding Str}"/>
<ContentControl Margin="3" Content="{Binding Image}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
lstBox.Items.Add(new Img("Value", myImage));

Related

In Xamarin Android, how can we implement a carousel view?

I am using xamarin android.
I have to display a horizontal scrollable list.
As I am a beginner to Xamarin Android, I am unable to find a proper solution.
I could not find a proper way yet.
I make a demo and it has three parts.
First, I create a Model class to define my datatype.
public class Photo
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string Url { get; set; }
}
Second, I create a ViewModel class to handle the data.
public class MyViewModel
{
public ObservableCollection<Photo> Photos { get; set; }
public MyViewModel()
{
Photos = new ObservableCollection<Photo>();
Photos.Add(new Photo() { Name = "Name1", Details = "Details1", Location = "Location1" });
Photos.Add(new Photo() { Name = "Name2", Details = "Details2", Location = "Location2" });
Photos.Add(new Photo() { Name = "Name3", Details = "Details3", Location = "Location3" });
}
}
Third, I bind the ViewModel to the MainPage and present it by a CarouselView.
In the MainPage.xaml.cs file
public MainPage()
{
this.BindingContext = new MyViewModel();
InitializeComponent();
}
In the MainPage.xaml file
<CarouselView ItemsSource="{Binding Photos}">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="20"
HeightRequest="100"
WidthRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}" HorizontalOptions="Center" VerticalOptions="Center" FontSize="Large"></Label>
<Label Text="{Binding Details}" HorizontalOptions="Center" VerticalOptions="Center" FontSize="Large"></Label>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
For more information you can refer to the Xamarin.Forms CarouselView Layout.

Can I populate a Label within my CollectionView with a value outside the ItemsSource List that populates the view?

I have a Label within my CollectionView that I need to populate with a value outside the ItemsSource List that populates the view.
The following code is an example of what I am trying to accomplish but it seems that the CollectionView is limiting the binding context to just the Items list. I have tried naming the label and setting it in my c# code but I cant seem to access the label in c#. I suppose I could build the whole page in c# rather than using the .xaml but unlike this example my actual code uses multiple templates and a template selector. If I could figure this out without rewriting hours of code I would prefer it.
ItemsPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="TabTest.Views.ItemsPage"
Title="{Binding Title}"
x:Name="BrowseItemsPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Clicked="AddItem_Clicked" />
</ContentPage.ToolbarItems>
<StackLayout Padding="10">
<Label Text="{Binding TestVal}" FontSize="16" HeightRequest="20" />
<!-- ^^^^ This label displays just as expected -->
<RefreshView IsRefreshing="{Binding IsBusy, Mode=TwoWay}" Command="{Binding LoadItemsCommand}">
<CollectionView x:Name="ItemsCollectionView"
ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10">
<Label x:Name="TestV" Text="{Binding Path=BindingContext.TestVal}" />
<!-- ^^^^ I want this Label to display the TestVal string in the ViewModel -->
<Label Text="{Binding Text}"
d:Text="{Binding .}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="{Binding Description}"
d:Text="Item descripton"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Tapped="OnItemSelected"></TapGestureRecognizer>
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</StackLayout>
</ContentPage>
ItemsViewModel.cs
namespace TabTest.ViewModels
{
public class ItemsViewModel : BaseViewModel
{
public ObservableCollection<Item> Items { get; set; }
public Command LoadItemsCommand { get; set; }
private string testVal;
public string TestVal // I want the value of this variable in that Label
{
get
{
return testVal;
}
set
{
testVal = value;
}
}
public ItemsViewModel()
{
Title = "Browse";
TestVal = "Value123";
Items = new ObservableCollection<Item>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
}
async Task ExecuteLoadItemsCommand()
{
IsBusy = true;
try
{
Items.Clear();
var items = await DataStore.GetItemsAsync(true);
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
}
I ended up using a dynamic resource in Xaml and used code behind to modify the resource when it needed to change.
Xaml:
<Label x:Name="TestV" Text="{DynamicResource TestValue}" />
Code Behind:
Application.Current.Resources["TestValue"] = NewValue;
App.xaml:
<x:String x:Key="TestValue">Value123</x:String>

How to set a binding to an element that was not instantiated in XAML code

I´m relative new to coding and I´m working on a little project. This is what I´m trying to do:
I defined a class "MyObject" with two properties:
namespace WpfApplication2
{
public class MyObject
{
public string Property1 { get; set; }
public int Property2 { get; set; }
public MyObject() : this("", 0)
{
}
public MyObject(string p1, int p2)
{
Property1 = p1;
Property2 = p2;
}
}
}
...then instantiated two objects of this class in code:
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public List<MyObject> listOfMyObject { get; set; }
public MyObject myObj1 { get; set; }
public MyObject myObj2 { get; set; }
public MainWindow()
{
InitializeComponent();
listOfMyObject = new List<MyObject>();
myObj1 = new MyObject("Hello", 1);
myObj2 = new MyObject("Bye", 2);
listOfMyObject.Add(myObj1);
listOfMyObject.Add(myObj2);
}
}
}
Now I want to bind each property of the two MyObject objects to the Content Property of a Label object. So there should be four Label objects:
- Label1 should display the value of Property1 of myObj1
- Label2 should display the value of Property2 of myObj1
- Label3 should display the value of Property1 of myObj2
- Label4 should display the value of Property2 of myObj2
I tried it this way:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Name="mywin">
<Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel>
<Label Name="Label1" Content="{Binding ElementName=myObj1, Path=Property1}"/>
<Label Name="Label2" Content="{Binding ElementName=myObj1, Path=Property2}"/>
</StackPanel>
<StackPanel>
<Label Name="Label3" Content="{Binding ElementName=myObj2, Path=Property1}"/>
<Label Name="Label4" Content="{Binding ElementName=myObj2, Path=Property2}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
... but it doesn´t work. Please help me to understand how to use the Binding correctly!
Greetings
// Even if I already figured out how to solve my problem, I would be pleased, // if someone could answer to the question at the end of this post!
Okay, now I figured out (with a little help from a friend), how to fix my problem:
I set the DataContext property of the MainWindow object, that contained the Label objects to itself by doing this:
mywin.DataContext = this;
So the code looks like this now:
public partial class MainWindow : Window
{
public List<MyObject> listOfMyObject { get; set; }
public MyObject myObj1 { get; set; }
public MyObject myObj2 { get; set; }
public MainWindow()
{
InitializeComponent();
listOfMyObject = new List<MyObject>();
myObj1 = new MyObject("Hello", 1);
myObj2 = new MyObject("Bye", 2);
listOfMyObject.Add(myObj1);
listOfMyObject.Add(myObj2);
// I added this code
mywin.DataContext = this;
}
}
And then I set the binding to the Content property of the four Label objects by doing this:
<Label Name="Label1" Content="{Binding Path=myObj1.Property1}" />
So my whole XAML code looks like this now:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Name="mywin">
<Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel>
<Label Name="Label1" Content="{Binding Path=myObj1.Property1}" />
<Label Name="Label2" Content="{Binding Path=myObj1.Property2}" />
</StackPanel>
<StackPanel>
<Label Name="Label3" Content="{Binding Path=myObj2.Property1}" />
<Label Name="Label4" Content="{Binding Path=myObj2.Property2}" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
NEW Question:
Now I would like to understand, why it doesn´t work the way I tried in the first way...
<Label Name="Label1" Content="{Binding ElementName=myObj1, Path=Property1}"/>
... when this would work:
<Label Name="Label1" Content="{Binding ElementName=Label2, Path=Content}"/>
<Label Name="Label2" Content="Hello">
The XAML code, in which the Label objects are instantiated and the C# code, in which the MyObject objects are instantiated, are both partial classes that belong together. In addition to that the MyObject objects myObj1 and myObj2 are properties of this class. So I thought that the Label-Elements in the XAML code should "know" about the MyObject objects myObj1 and myObj2 and therefore be able to reference them as source elements in the ElementName property of the Binding object. Thinking this way, I thought I must only set the Path property of the Binding object to the Property which value the Label object should display.
Can you help me to understand, where my idea of Binding is wrong? Thank you!

WP7 - Call bound number on clicking Listbox item

So I have a list of objects containing a name and number bound to a listbox in XAML. The listbox displays the number fine, but I want it to call the phone number using phonecall on click. Here is the onlick code:
private void taxiListItem_Click(object sender, RoutedEventArgs e)
{
Microsoft.Phone.Tasks.PhoneCallTask phonecall = new Microsoft.Phone.Tasks.PhoneCallTask();
phonecall.PhoneNumber = "213";
phonecall.Show();
}
and here is where I define the TaxiCompany object that populates the list.
public class TaxiCompany {
public String CoName { get; set; }
public String Phone { get; set; }
public TaxiCompany(String coname, String phone) {
this.CoName = coname;
this.Phone = phone;
}
}
The phone call works fine when I hardcode the number . Now, when I set phonecall.Phonenumber = sender.getPhone() or e.Phone() or any variant of the two, its marked as an undefined method. Am I doing something fundamentally wrong here? I assume object sender or e is the list item being clicked on.
Note: the listbox in the XAML displays both the phone number and address just fine
<Button Click="taxiListItem_Click" Width ="436" Height="120">
<Button.Content>
<StackPanel Orientation="Vertical" Height=" 80">
<StackPanel Orientation="Horizontal" Height="40" Width="436">
<TextBlock Width="436" FontSize="30" Text= "{Binding CoName}" Height="40"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="40" Width="436">
<TextBlock Name ="PhoneNo" Width="300" FontSize="22" Text= "{Binding Phone}" Height="40"/>
</StackPanel>
</StackPanel>
</Button.Content>
</Button>
First time working with C# / Silverlight so any help would be apprecaited.
Try this. The listbox shows the taxi companies and selecting an item in the list causes the phone numbe rot try and be dialed.
Notice that it's not necessary to add buttons to the list and that it's necessary to cast the variables passed to the selection event. (Could also cast the sender to a listbox and then cast the selected item.)
xaml:
<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding TaxiCompanies}" SelectionChanged="MainListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Height=" 80">
<TextBlock Width="436" FontSize="30" Text= "{Binding CoName}" Height="40"/>
<TextBlock Name ="PhoneNo" Width="300" FontSize="22" Text= "{Binding Phone}" Height="40"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
cs:
// class used for example. Another name would be more appropriate
public class ViewModel
{
public ObservableCollection<TaxiCompany> TaxiCompanies { get; private set; }
public ViewModel()
{
TaxiCompanies = new ObservableCollection<TaxiCompany>();
TaxiCompanies.Add(new TaxiCompany("AAA Cabs", "123-456-789"));
TaxiCompanies.Add(new TaxiCompany("BBB Taxis", "111234329"));
TaxiCompanies.Add(new TaxiCompany("CCC Cars", "98765432"));
}
}
public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
DataContext = new ViewModel();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var phonecall = new PhoneCallTask();
phonecall.PhoneNumber = ((TaxiCompany)(((object[])(e.AddedItems))[0])).Phone;
phonecall.Show();
// Reset selected index to -1 (no selection)
MainListBox.SelectedIndex = -1;
}

WPF: Nested collection binding

My application shows a question and possible answers on that question. Now I want to give the correct answer (specified in the "CorrectAnswer" property) a green color. Can someone help me? Thanks.
public class Exercise
{
public string QuestionText { get; set; }
public int CorrectAnswer { get; set; }
public Answer[] Answers { get; set; }
...
}
public class Answer
{
public string AnswerText { get; set; }
...
}
XAML:
<StackPanel Orientation="Vertical">
<Label Content="{Binding Path=QuestionText}"></Label>
<ItemsControl ItemsSource="{Binding Path=Answers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Path=AnswerText}"></Label>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
If you have some idea on ValueConverter in WPF, better make use of that. That will give you a lot of flexibility and easy to implement. Please let me know, if you still have some doubt.

Resources