How bind ObservableCollection to ListBox? - c#

I have class
public class Clip
{
public string ID { get; set; }
public string Name { get; set; }
public int? Duration { get; set; }
}
And ObservableCollection
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get { return _clipsFound; }
set
{
_clipsFound = value;
OnPropertyChanged();
}
}
OnPropertyChanged() is invoked when I do
_clipsFound = collection
I want binding data from collection to ListBox with three columns: ID, Name, Duration
Initialize
ID = id;
collection = new ObservableCollection<Clip>();
_clipsFound = collection;
_clipsFound.Clear();
ICollection<Clip> ClipF = await Service.GetClips(ID);
ICollection<Clip> Clipcol = ClipF;
collection = new ObservableCollection<Clip>(Clipcol);
I try do this, but it doesn't work
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Title}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
Foreground="#FF4F4F4F"
FontSize="12"
Margin="55 0 0 0"/>
<TextBlock Grid.Column="1"
Margin="0 0 45 0"
Text="{Binding Duration}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontSize="11"
Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What did I do wrong?

You cannot send data from viewmodel to view without setting DataContext. DataContext is like channel or bridge between ViewModel and View.
This code sets DataContext:
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
Let's see work example:
Your ViewModel:
public class MainWindowViewModel
{
publicMainWindowViewModel
{
LoadData();
}
private void LoadData()
{
_clipsFound=new ObservableCollection<Clip>();
for(int startIndex=0; startIndex<10; startIndex++)
{
collection.Add(new Clip(){ID=startIndex, Name="Bob", Duration=startIndex++});
}
}
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get
{
return _clipsFound;
}
set
{
_clipsFound = value;
}
}
}
Your XAML:
<Window x:Class="DataGridSelectedItemsWpfApplication.MainWindow"
...The code omitted for the brevity...
xmlns:vm="clr-namespace:DataGridSelectedItemsWpfApplication.ViewModel"
Title="MainWindow" WindowStartupLocation="CenterScreen" Height="550" Width="525">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ID}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Margin="2" Foreground="#FF4F4F4F"/>
<TextBlock Grid.Column="1" Margin="2" Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="#FF4F4F4F" FontSize="12"/>
<TextBlock Grid.Column="2" Margin="2" Text="{Binding Duration}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
There are many ways to set DataContext.

Related

Change color when selected on UWP C#

I need to change the color of a rectangle in a GridView when the item is selected.
Unselected item
Selected item
My Main Page in XAML.
<Page
x:Class="GridViewWithSelectedItem.Views.MainPage"
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:views="using:GridViewWithSelectedItem.Views"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="TileTemplate" x:DataType="views:Article">
<Border BorderThickness="2,2,2,2" BorderBrush="#FF868484" Margin="3,3,3,3" HorizontalAlignment="Stretch" MaxWidth="600" MinWidth="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="60"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle Fill="Black" Grid.RowSpan="3"/>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap" Foreground="DarkBlue" FontWeight="Bold" Text="{x:Bind Number}"/>
<TextBlock FontSize="20" TextWrapping="Wrap" Foreground="DarkBlue" Text="{x:Bind Title}" FontWeight="Bold"/>
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="1" FontSize="20" Text="{x:Bind Description}" TextWrapping="WrapWholeWords"/>
<StackPanel Background="LightBlue" Padding="5,0,0,0" Grid.Row="2" Grid.Column="1">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap">Date :</TextBlock>
<TextBlock Foreground="Red" FontSize="20" TextWrapping="Wrap" Text="{x:Bind Date}" FontWeight="Bold"/>
</StackPanel>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</Page.Resources>
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<Grid Background="White" VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="0,25,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="600"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="800"/>
</Grid.RowDefinitions>
<TextBlock Text="The Guardian" FontSize="35" FontWeight="Bold" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
<GridView
BorderThickness="2,2,0,2" BorderBrush="#FF868484"
MinWidth="600"
Grid.Column="0"
Grid.Row="1"
Padding="5,5,5,5"
HorizontalAlignment="Center"
CanDragItems="False"
IsItemClickEnabled="true"
IsTapEnabled="False"
IsSwipeEnabled="False"
ItemsSource="{x:Bind Articles}"
ItemTemplate="{StaticResource TileTemplate}"
SelectedItem="{x:Bind Mode=TwoWay, Path=SelectedArticle}"
/>
<RelativePanel Grid.Row="1" Grid.Column="1" Background="WhiteSmoke" BorderThickness="2" BorderBrush="#FF868484" Padding="10">
<Grid RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True">
<Grid VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap" Foreground="DarkBlue" FontWeight="Bold" Text="{x:Bind Path=SelectedArticle.Number, Mode=OneWay}"/>
<TextBlock FontSize="20" TextWrapping="Wrap" Foreground="DarkBlue" Text="{x:Bind Path=SelectedArticle.Title, Mode=OneWay}" FontWeight="Bold"/>
</StackPanel>
<TextBlock Grid.Row="1" FontSize="20" Text="{x:Bind Path=SelectedArticle.Description, Mode=OneWay}" TextWrapping="WrapWholeWords"/>
</Grid>
</Grid>
<RelativePanel Background="LightBlue" Padding="5,0,0,0" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap">Date :</TextBlock>
<TextBlock Foreground="Red" FontSize="20" TextWrapping="Wrap" Text="{x:Bind Path=SelectedArticle.Date, Mode=OneWay}" FontWeight="Bold"/>
</StackPanel>
</RelativePanel>
</RelativePanel>
</Grid>
</Grid>
</Page>
And the class of my XAML Page.
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.UI.Xaml.Controls;
namespace GridViewWithSelectedItem.Views
{
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
public ObservableCollection<Article> Articles;
private Article _selectedArticle;
public Article SelectedArticle
{
get { return _selectedArticle; }
set { Set(ref _selectedArticle, value); }
}
public MainPage()
{
InitializeComponent();
Articles = new ObservableCollection<Article>();
Articles.Add(new Article(0, "Uighurs", "Being young' leads to detention in China's Xinjiang region", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(1, "Brexit", "Chances of Brexit deal hang on Boris Johnson and Ursula von der Leyen dinner", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(2, "Environment", "Secretive ‘gold rush’ for deep-sea mining dominated by handful of firms", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(3, "Juukan Gerge induiry", "Juukan Gorge inquiry: Rio Tinto's decision to blow up Indigenous rock shelters 'inexcusable'", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(4, "Australia", "British journalist uncovered Australian woman's alleged plan to kill parents on dark web, police say", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(5, "Coronavirus", "Nine out of 10 in poor nations to miss out on inoculation as west buys up Covid vaccines", DateTime.Parse("09/12/2020")));
}
public event PropertyChangedEventHandler PropertyChanged;
private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Article
{
public int Number { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
public Article(int number, string title, string description, DateTime date)
{
Number = number;
Title = title;
Description = description;
Date = Date;
}
}
}
I see AutomationProperty.name can help me but i don't understand how to use it.
I found a way to change the color of a selected item in my class but i need to recreate the collection and i cost lot of resources. I think its possible to make it in XAML code.
Edit: I made a simple exemple of my code.
OneDrive link
You could add a Brush property into the Article class, and bind the Brush property to Rectangle.Fill property of your DataTemplate to change the color when an item of GridView control is selected.
Please check the following code:
In DataTemplate of your xaml file:
<Rectangle x:Name="rectangle" Fill="{x:Bind Brush}" Grid.RowSpan="3"/>
……
<GridView …… SelectionChanged="GridView_SelectionChanged" />
In code-behind:
public class Article
{
……
public SolidColorBrush Brush { get; set; }
public Article(int number, string title, string description, DateTime date)
{
……
Brush = new SolidColorBrush(Colors.Black);
}
}
Add a _preSelectedArticle property to save the previous item in MainPage class:
private Article _preSelectedArticle;
Change the value of Brush property of selected item and previous selected item:
private void GridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(_preSelectedArticle==null)
{
SelectedArticle.Brush.Color = Colors.Green;
_preSelectedArticle = SelectedArticle;
}
if (_preSelectedArticle!=null&&_preSelectedArticle!= SelectedArticle)
{
_preSelectedArticle.Brush.Color = Colors.Black;
SelectedArticle.Brush.Color = Colors.Green;
_preSelectedArticle = SelectedArticle;
}
}

Disable Itemscontrol components on button click

I'm learning wpf through mvvm.
My application consist of below logic.
Form which has a button that will add a selected components horizontally from Itemcontrol like textbox, combobox and rich textbox and a button whenever the button is clicked.
When the add button is clicked the specified set of components will be added in the line information dynamically.
2) Data will be inserted into the table after pressing the add info button.
3) The issue is after clicking the add info button, the components in the itemscontrol should be readonly. This is the place I'm struggling as of now.
Model.cs:
public class textboxModel
{
public string Text { get; set; }
public string lblText { get; set; }
public string isactive { get; set; }
public bool txtboxreadonly { get; set; }
}
public class ButtonDataModel
{
public string Content { get; set; }
public ICommand Command { get; set; }
public string column { get; set; }
public string isactive { get; set; }
public bool buttreadonly { get; set; }
}
ViewModel.cs:
public class viewmodel : notifyproperties
{
public Relaycommand Status { get; set; }
public Relaycommand AddCommand { get; set; }
public labelconversionOnPauseButtonclick pauseclick = new labelconversionOnPauseButtonclick();
public auditinformation auditid = new auditinformation();
public ButtonDataModel bdm = new ButtonDataModel();
public auditinformation adt
{
get { return auditid; }
set
{
if (value != auditid)
{
auditid = value;
OnPropertyChanged("adt");
}
}
}
public labelconversionOnPauseButtonclick res
{
get { return pauseclick; }
set
{
if (value != pauseclick)
{
pauseclick = value;
OnPropertyChanged("res");
}
}
}
public viewmodel()
{
Status = new Relaycommand(pauseclick.Statusdata);
AddCommand = new Relaycommand(o => auditid.addcommand());
}
}
public class auditinformation : notifyproperties
{
public Relaycommand Command { get; set; }
private string _lines;
public string Lines
{
get { return this._lines; }
set
{
this._lines = value;
this.OnPropertyChanged("Lines");
}
}
private readonly ObservableCollection<ButtonDataModel> _MyDatabutton = new ObservableCollection<ButtonDataModel>();
public ObservableCollection<ButtonDataModel> MyData { get { return _MyDatabutton; } }
private readonly ObservableCollection<textboxModel> _MyDatatxtbox = new ObservableCollection<textboxModel>();
public ObservableCollection<textboxModel> MyDatatxtbox { get { return _MyDatatxtbox; } }
private readonly ObservableCollection<LabelDataModel> _MyDataLabel = new ObservableCollection<LabelDataModel>();
public ObservableCollection<LabelDataModel> MyDataLabel { get { return _MyDataLabel; } }
public void addcommand()
{
int num= 1;
for (int i = 0; i < num; i++)
{
MyDatatxtbox.Add(new textboxModel
{
isactive = "1",
});
MyData.Add(new ButtonDataModel
{
Command = new Relaycommand(o => search()),
Content = "Add info",
isactive = "1",
});
}
}
public void search( )
{
var asss = MyDatatxtbox.Where(a=> a.isactive == "1").Select(a => a.Text);
var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach (var s in asss)
{
foreach (var a in itemstoremove)
{
if (a.isactive == "1")
{
MessageBox.Show(s);
buttreadonly = true;
}
}
}
// var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach(var a in itemstoremove)
{
a.isactive = "0";
}
//foreach (var a in itemstoremove)
//{
// a.txtboxreadonly = true;
//}
// var itemstoremovebutton = MyData.Where(i => i.isactive == "1").ToList();
// foreach (var a in itemstoremovebutton)
// {
//// MyData.Remove(a);
// a.isactive = "0";
// }
}
}
window.xaml:
<GroupBox Header="Audit Information" Grid.Row="1">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Text="Member ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" Text="Claim Number"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="3" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="4" Text="Date Audited"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="5" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="6" Text="Query ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="7" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="8" Text="Audit ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="9" Width="85" ></TextBox>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="85" Height="25" Command="{Binding AddCommand}" Content="Add" Grid.Column="10"></Button>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Margin="0,0,0,0" Header="Line Information" >
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3.2*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.8*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Height="22" Grid.Column="0">
<Label HorizontalAlignment="Center" Content="DOS" />
</StackPanel>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="1">
<Label HorizontalAlignment="Center" Content="CPT" />
</StackPanel>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="2">
<Label HorizontalAlignment="Right" Content="Open-close Modifier" Margin="0,0,-17,0" Width="121" />
</StackPanel>
<ItemsControl Grid.Column="2" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="3">
<Label HorizontalAlignment="Center" Content="Comments" />
</StackPanel>
<ItemsControl Grid.Column="3" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="4">
<Label HorizontalAlignment="Center" Content="Line Status" />
</StackPanel>
<ItemsControl Grid.Column="4" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10,0,0,50">
<ComboBox IsEnabled= "{Binding txtboxreadonly}" Margin="0,0,0,0" Height="25" Width="95" >
<ComboBoxItem Content="Coffie"></ComboBoxItem>
<ComboBoxItem Content="Tea"></ComboBoxItem>
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="5">
<Label HorizontalAlignment="Center" Content="Additional Comments" />
</StackPanel>
<ItemsControl Grid.Column="5" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Column="6" Grid.Row="1" ItemsSource="{Binding adt.MyData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<Button Margin="0,0,0,0" Height="25" Width="55" Content="{Binding Content}" Command="{Binding Command}" >
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ScrollViewer>
</GroupBox>
</Grid>
</Grid>
</TabItem>
</TabControl>
So the question is how to disable/readonly the Line Information ,textbox and cpt on add info button click.
Dirty way would be adding a "global" bool property in your ViewModel and binding it to your Controls IsEnabled/ReadOnly Properties.

Get index of clicked row from a nested listview - UWP

I have a nested listview. When clicks on it's button I want to get it's row index. Now I got the index as -1 always.
<ListView x:Name="Mainlist" HorizontalAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBooksList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView x:Name="sublist1" ItemsSource="{x:Bind CurrentFoldersArray}" Grid.Column="0" BorderBrush="Black" BorderThickness="0,0,0,1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentFoldersList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Foreground="Black" FontWeight="Bold" Grid.Column="0" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{x:Bind BookCode}"/>
<ListView x:Name="sublist2" ItemsSource="{x:Bind CurrentBookArray1}" Grid.Column="1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBusList1">
<Button Width="120" Height="40" Text="{x:Bind Lockbook}" Click="LockMyBook_btn_Click">
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
private void LockMyBook_btn_Click(object sender, RoutedEventArgs e)
{
int selectedIndx = Mainlist.SelectedIndex; //always return -1
}
How can I get the row number of mainlist view, when user clicks on it's inner listview's button?
Yes it runs well. By getting row number of mainlist, I want to access corresponding items in CurrentBooksList
Well, it's strange. If you're using a basic UWP button control, it doesn't have Text property, your code should not work. But I didn't care about this point, your question was not related to it.
In your button's click event handler, you could get its DataContext, then you could convert it to an CurrentBusList1 object. By this CurrentBusList1 object, you could do some judgements from your 'Mainlist' ItemsSource and get the selected CurrentBooksList object.
public sealed partial class MainPage : Page
{
public ObservableCollection<CurrentBooksList> currentBooksLists { get; set; }
public MainPage()
{
this.InitializeComponent();
currentBooksLists = new ObservableCollection<CurrentBooksList>();
ObservableCollection<CurrentFoldersList> currentFoldersLists = new ObservableCollection<CurrentFoldersList>();
currentFoldersLists.Add(new CurrentFoldersList() { BookCode = "abc123", CurrentBookArray1 = new ObservableCollection<CurrentBusList1>() { new CurrentBusList1() { Lockbook = "123abc" }, new CurrentBusList1() { Lockbook = "123def" } } });
currentFoldersLists.Add(new CurrentFoldersList() { BookCode = "def456", CurrentBookArray1 = new ObservableCollection<CurrentBusList1>() { new CurrentBusList1() { Lockbook = "def456" } } });
currentBooksLists.Add(new CurrentBooksList() { CurrentFoldersArray = currentFoldersLists });
}
private void Button_Click(object sender, RoutedEventArgs e)
{
int index;
var subSelectedItem = ((FrameworkElement)sender).DataContext as CurrentBusList1;
foreach (var item in currentBooksLists)
{
foreach (var folder in item.CurrentFoldersArray)
{
foreach (var bus in folder.CurrentBookArray1)
{
if (bus == subSelectedItem)
{
index = currentBooksLists.IndexOf(item);
break;
}
}
}
}
}
}
public class CurrentBooksList
{
public ObservableCollection<CurrentFoldersList> CurrentFoldersArray { get; set; }
}
public class CurrentFoldersList
{
public string BookCode { get; set; }
public ObservableCollection<CurrentBusList1> CurrentBookArray1 { get; set; }
}
public class CurrentBusList1
{
public string Lockbook { get; set; }
}
<ListView x:Name="Mainlist" HorizontalAlignment="Stretch" ItemsSource="{x:Bind currentBooksLists}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBooksList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView x:Name="sublist1" ItemsSource="{x:Bind CurrentFoldersArray}" Grid.Column="0" BorderBrush="Black" BorderThickness="0,0,0,1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentFoldersList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Foreground="Black" FontWeight="Bold" Grid.Column="0" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{x:Bind BookCode}"/>
<ListView x:Name="sublist2" ItemsSource="{x:Bind CurrentBookArray1}" Grid.Column="1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBusList1">
<Button Width="120" Height="40" Content="{x:Bind Lockbook}" Click="Button_Click">
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

WPF MVVM properties binding not working properly

I have created a view model which has a single property for a student model, that I am then binding to a control in my XAML. But nothing is appearing when I execute the application.
I am setting data context in my app.xaml.cs as follows:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Registrationformusinemvvm.MainWindow window = new MainWindow();
VMUser VM = new VMUser();
window.DataContext = VM;
window.Show();
}
Why is the binding not working?
This is my view model:
public class VMUser:BaseClass
{
private student _currentStudent;
public student CurrentStudent
{
get { return _currentStudent; }
set {
_currentStudent = value;
OnPropertyChanged("CurrentStudent");
}
}
}
My Student model class:
public class student:BaseClass
{
private string name="sumit";
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
private int rollNum;
public int RollNum
{
get { return rollNum; }
set { rollNum = value;OnPropertyChanged("RollNum"); }
}
private int phNum;
public int PhNum
{
get { return phNum; }
set { phNum = value;OnPropertyChanged("PhNum"); }
}
private string sub;
public string Sub
{
get { return sub; }
set { sub = value;OnPropertyChanged("Sub"); }
}
}
My XAML:
<Window x:Class="Registrationformusinemvvm.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:Registrationformusinemvvm"
xmlns:vm="clr-namespace:Registrationformusinemvvm.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<!--<Window.DataContext>
<vm:VMUser/>
</Window.DataContext>-->
<Window.Resources>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name" Grid.Column="0" Grid.Row="0" FontSize="14"
FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="Roll Number" Grid.Column="0" Grid.Row="1" FontSize="14"
FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="Subject" Grid.Column="0" Grid.Row="2" FontSize="14"
FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="Phone Number" Grid.Column="0" Grid.Row="3"
FontSize="14" FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBox Name="tbName" Text="{Binding CurrentStudent.Name,Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="0"
Width="120" Height="30" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBox Name="tbRollnum" Text="{Binding CurrentStudent.RollNum}"
Grid.Column="1" Grid.Row="1" Width="120" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Name="tbSub" Text="{Binding CurrentStudent.Sub}"
Grid.Column="1" Grid.Row="2" Width="120" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Name="tbPh" Text="{Binding CurrentStudent.PhNum}"
Grid.Column="1" Grid.Row="3" Width="120" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Name="tbSubmit" Content="Submit" Grid.ColumnSpan="3"
Grid.Row="4" Height="30" Width="100" HorizontalAlignment="Center"/>
</Grid>
</Window>
My guess is that your binding isn't working because your _currentStudent is null by default. Initialize your _currentStudent if null.
public student CurrentStudent
{
get { return _currentStudent = (_currentStudent ?? new student()); }
set
{
_currentStudent = value; OnPropertyChanged("CurrentStudent");
}
}
You need to add OnPropertyChanged in your model class.
void OnPropertyChanged(string prop)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
public event PropertyChangedEventHandler PropertyChanged;
As per your above code you cant assigned the value to CurrentStudent Property so
can you please check do you have the value to CurrentStudent property.
Thank you for your question
Remove StartupUri="YourXamlFile.xaml" from App.Xaml

Dictionary (ObservableCollection) binding to ListView in Windows Phone 8.1

I am trying to bind a dictionary to two textblocks in a listview. The listview ItemsSource binding is defined in the code behind and the text blocks content is in the XAML.
I am able to display the items but they are displayed with square brackets around each row like [stringA, stringB]. However, this format will not work. The latest code that I tried was by setting the Key and Value which did not work was:
XAML:
<ListView Name="lvListLogs"
Margin="0,10,0,0">
<ListView.ItemTemplate>
<DataTemplate x:Name="ListItemTemplate">
<Grid Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="122"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="104"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="tb_PointName" Grid.Column="1"
Text="{Binding Key}"
Margin="10,0,0,0" FontSize="40"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FFFE5815" />
<TextBlock x:Name="tb_PointValue" Grid.Column="1"
Text="{Binding Value}"
Margin="10,0,0,0" FontSize="40"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FFFE5815" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C# (abridged for clarity):
public Dictionary<string, string> mydict2 { get; set; }
mydict2 = new Dictionary<string, string>();
if (item != null)
{
var props = item.GetType().GetRuntimeProperties();
foreach (var prop in props)
{
foreach (var itm in group1.Items.Where(x => x.UniqueId == prop.Name))
{
var _Title = prop.Name;
var _Value = prop.GetValue(item, null);
string propertyValue;
string propertyName;
propertyValue = Convert.ToString(_Value);
propertyName = _Title;
mydict2.Add(_Title, propertyValue);
}
}
//binding here
lvListLogs.ItemsSource = mydict2;
}
Any assistance would be appreciated.
Your code works fine, the problem is you set the same Grid.Column for both TextBlocks. The first column index should be zero:
<TextBlock x:Name="tb_PointName" Grid.Column="0" ...
To achieve the required binding, instead of the Dictionary I used an ObservableCollection with the class and constructor.
To databind the listview (xaml) to ObservableCollection:
Create the Class with Constructor
public class PointInfoClass
{
public string PointName { get; set; }
public string PointValue { get; set; }
public PointInfoClass(string pointname, string pointvalue)
{
PointName = pointname;
PointValue = pointvalue;
}
}
Create collection of the PointInfoClass
public ObservableCollection<PointInfoClass> PointInfo
{
get
{
return returnPointInfo;
}
}
Instantiate the collection
ObservableCollection<PointInfoClass> returnPointInfo = new ObservableCollection<PointInfoClass>();
Add item to collection
returnPointInfo.Add(new PointInfoClass(string1, string2));
Databind to the ObservableCollection name.
The xaml code:
<ListView
Grid.Row="1"
ItemsSource="{Binding PointInfo}"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
Margin="19,0.5,22,-0.333"
x:Name="lvPointInfo"
Background="White">
<ListView.ItemTemplate>
<DataTemplate >
<Grid Margin="0,0,0,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="270"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="1" VerticalAlignment="Top">
<TextBlock x:Name="tb_PointSubTitle" Grid.Column="1"
Text="{Binding PointName}"
Margin="10,0,0,0" FontSize="20"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FF5B5B5B"
/>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="2" VerticalAlignment="Top" HorizontalAlignment="Right">
<TextBlock x:Name="tb_PointValue"
Grid.Column="1"
Text="{Binding PointValue}"
Margin="0,5,0,0" FontSize="20"
HorizontalAlignment="Right"
TextWrapping="Wrap"
FontWeight="Normal"
Foreground="Black" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Set the DataContext of the ListView
lvPointInfo.DataContext = this;
This code is edited for clarity.

Categories