How to get item details from an ItemCollection in a GridView - c#

I've a GridView page with different elements (ItemExplorer). Each element has two TextBlocks (Name & Description) and they're binding to a Collection.
I want that to when I click in a single element, a new page should be opened with the item details (ItemViewer), like a name or description...
I'm new in C#, so I appreciate any help or support! :)
This is my current code:
ItemExplorer.xaml:
<GridView ItemsSource="{Binding ItemList}">
<GridView.ItemTemplate>
<DataTemplate>
<Border DoubleTapped="GoToItemViewer_DoubleTapped">
<StackPanel>
<TextBlock Name="ItemName" Text="{Binding ItemName}"/>
<TextBlock Name="ItemDescription" Text="{Binding ItemDescription}"/>
</StackPanel>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
ItemExplorer.xaml.cs:
namespace Test001.Pages
{
public sealed partial class ItemExplorer : Page
{
public ItemCollection MyItemCollection;
public ItemExplorer()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
MyItemCollection = new ItemCollection();
this.DataContext = MyItemCollection;
}
// Go to ItemViewer
private void GoToItemViewer_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
if (this.Frame != null)
{
// SEND THE ITEM DETAILS AS PARAMTER TO ITEMVIEWER
this.Frame.Navigate(typeof(ItemViewer));
}
}
}
}
ItemCollection.cs
Collectionnamespace Test001.DataSource
{
public class CollectionFiles: BindableBase
{
private ItemCollection _ItemList = new ItemCollection();
public ItemCollection ItemList
{
get { return _ItemList; }
set { SetProperty(ref _ItemList, value); }
}
public CollectionFiles()
{
_ItemList.Add(new FileModel()
{
ItemName = "ItenName0",
ItemDescription = "Iten Description0",
});
_ItemList.Add(new FileModel()
{
ItemName = "ItenName1",
ItemDescription = "Iten Description1",
});
_ItemList.Add(new FileModel()
{
ItemName = "ItenName2",
ItemDescription = "Iten Description2",
});
_ItemList.Add(new FileModel()
{
ItemName = "ItenName3",
ItemDescription = "Iten Description3",
});
}
}
}
ItemViewer.xaml.cs
namespace mydox104.Pages
{
public sealed partial class DocumentViewer : mydox104.Common.LayoutAwarePage
{
public DocumentViewer()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// GET THE ITEM DETAILS
string file_name = e.Parameter as string;
if (!string.IsNullOrWhiteSpace(file_name))
{
pageTitle.Text = file_name;
}
else
{
pageTitle.Text = e.Parameter.ToString();
}
}
}
}
ItemViewer.xaml
<Grid Height="225">
<TextBlock x:Name="Item-Name" Text=""/>
<TextBlock x:Name="Item-Description" Text=""/>
</Grid>

Set in GridView:
<GridView IsItemClickEnabled="True" ItemClick="ItemClicked" ItemsSource="{Binding ItemList}">
in ItemExplorer.xaml.cs
private void ItemClicked(object sender, ItemClickEventArgs e)
{
var clickedItem = e.ClickedItem as ItemCollection;
if (clickedItem != null )
{
this.Frame.NavigateTo(typeof(ItemViewer), clickedItem);
}
}
in ItemViewer.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ItemCollection myElement = e.Parameter as ItemCollection;
...
}
Instead of
public ItemCollection MyItemCollection;
i'd just use
public ObservableCollection<FileModel> Items;
I hope it will help you somehow. However I encourage you to look about MVVM pattern. It is really useful in developing WPF/WinRT applications. (check also MVVM Light framework which gives you for instance Messanger class - which have ability to "send objects/messages" between classes).

Related

UWP AdvancedCollectionView filter not working with strings

I have a AdvancedCollectionView from Windows Community Toolkit version 6.1.1 and trying to use it to filter out on 2 string properties.
I have created a simple app to reproduce the issue : https://github.com/touseefbsb/UWP-Filter-List
It has a textbox for filtering between StartNumber and EndNumber properties of items.
but as soon as I enter text "123" into it, it shows no item in the ListView when it should actually show only the first item, based on the test logic.
Code
MainPage.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox
x:Name="SearchTicketBooksBox"
Width="300"
Header="Search"
TextChanged="SearchTicketBooks_TextChanged" />
<ListView
x:Name="TicketBooksListView"
Grid.Row="1"
Margin="4,0,0,0"
ItemsSource="{x:Bind ViewModel.TicketBooks}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="app1:TicketBookDto">
<StackPanel Margin="20">
<TextBlock Text="{x:Bind StartNumber}" />
<TextBlock Text="{x:Bind EndNumber}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainViewModel ViewModel { get; }
public MainPage() { InitializeComponent(); ViewModel = new MainViewModel(); }
private void SearchTicketBooks_TextChanged(object sender, TextChangedEventArgs e)
{
if (ViewModel != null)
{
if (string.IsNullOrWhiteSpace(SearchTicketBooksBox.Text))
{
ViewModel.TicketBooks.Filter = _ => true;
}
else
{
ViewModel.TicketBooks.Filter = x => ((TicketBookDto)x).StartNumber == SearchTicketBooksBox.Text;
//{
// var startNumber = Convert.ToInt32(((TicketBookDto)x).StartNumber);
// var endNumber = Convert.ToInt32(((TicketBookDto)x).EndNumber);
// var searchText = Convert.ToInt32(SearchTicketBooksBox.Text);
// return searchText >= startNumber && searchText <= endNumber;
//};
}
}
}
private void Page_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
ViewModel.TicketBooks.Add(new TicketBookDto { StartNumber = "123", EndNumber = "456" });
ViewModel.TicketBooks.Add(new TicketBookDto { StartNumber = "789", EndNumber = "987" });
}
}
MainViewModel
public class MainViewModel : INotifyPropertyChanged
{
private readonly ObservableCollection<TicketBookDto> _ticketBooksPrivate = new ObservableCollection<TicketBookDto>();
private AdvancedCollectionView ticketBooks;
public AdvancedCollectionView TicketBooks
{
get
{
if (ticketBooks is null)
{
ticketBooks = new AdvancedCollectionView(_ticketBooksPrivate, true);
ticketBooks.ObserveFilterProperty(nameof(TicketBookDto.StartNumber));
ticketBooks.ObserveFilterProperty(nameof(TicketBookDto.EndNumber));
}
return ticketBooks;
}
set => Set(ref ticketBooks, value);
}
#region INotifyStuff
public event PropertyChangedEventHandler PropertyChanged;
protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
}
TicketBookDto
public partial class TicketBookDto
{
public string StartNumber { get; set; }
public string EndNumber { get; set; }
}
I have commented out code of the actual logic I need in the filter, which is to show the list items only those who have the search number between their "StartNumber" and "EndNumber" properties. But for simplicity I am using a simple match to StartNumber logic to find out why it aint working. Also when I add a boolean property and simply filter using that property then it works fine, its just not working with these string properties.
I'm afraid you can't use Filter in TextChanged event, please refer the source code here.
if (_filter != null)
{
for (var index = 0; index < _view.Count; index++)
{
var item = _view.ElementAt(index);
if (_filter(item))
{
continue;
}
RemoveFromView(index, item);
index--;
}
}
When you input text in the SerchBox and if the text is not equal to the filter property, the item will be RemoveFromView. So it will make the next input not effect. For this design, we suggest you make submit button to filter the data after finished input.
And If you do want to filter in the TextChanged, you could call ViewModel.TicketBooks.Filter = _ => true; to reset the viewtiems before set Filter delegate method like the following.
private void SearchTicketBooks_TextChanged(object sender, TextChangedEventArgs e)
{
if (ViewModel != null)
{
if (string.IsNullOrWhiteSpace(SearchTicketBooksBox.Text))
{
ViewModel.TicketBooks.Filter = _ => true;
}
else
{ // reset the filter
ViewModel.TicketBooks.Filter = _ => true;
ViewModel.TicketBooks.Filter = x => ((TicketBookDto)x).EndNumber == SearchTicketBooksBox.Text;
}
}
}

Couldn't load combobox itemsource after deserialization in WPF

I'm facing a problem where I can't reload a serialiazed object (using NewtonsoftJson) into cascading comboboxes. I'm also using the Prism MVVM lib.
While at first start my application is working as expected:
so I am able to select values from the second combobox based on the first combobox, but when I save the model and reload it I've two main issues:
The SelectedItem property never get set (even the debugger shows that it's not null)
The second combobox stays empty eventhough the values seems to be loaded, that looks like:
What am I doing wrong here? Also, I don't like the ComboboxSelectionChanged approach, so maybe someone can point me to the MVVM based approach.
Here is the minimal working example:
MainWindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ViewModel viewModel;
public MainWindow()
{
InitializeComponent();
viewModel = new ViewModel();
ConstructRandomData();
DataContext = viewModel;
}
private void ConstructRandomData()
{
// Construct data
for (int i = 0; i < 5; i++)
{
var ids = new List<SubId>();
for (int r = 0; r < 10; r++)
{
ids.Add(
new SubId
{
Name = $"Id_{i}.{r}"
}
);
}
viewModel.MainIds.Add(
new MainId
{
Name = $"MainId{i}",
SubIds = ids
});
}
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox combo = sender as ComboBox;
if (combo.SelectedItem is MainId selectedItem)
{
var subIdList = (from mainId in viewModel.MainIds
where mainId.Name.Equals(selectedItem.Name)
select mainId.SubIds).First();
viewModel.SubIds.Clear();
viewModel.SubIds.AddRange(subIdList.ToArray());
}
}
private void SaveButtton_Click(object sender, RoutedEventArgs e)
{
File.WriteAllText("savedData.json", JsonConvert.SerializeObject(viewModel));
}
private void LoadButton_Click(object sender, RoutedEventArgs e)
{
ViewModel deserializedModel = JsonConvert.DeserializeObject<ViewModel>(File.ReadAllText("savedData.json"));
viewModel.MainIds = deserializedModel.MainIds;
viewModel.SubIds = deserializedModel.SubIds;
}
}
public class ViewModel : BindableBase
{
public ObservableCollection<MainId> MainIds { get; set; } = new ObservableCollection<MainId>();
public ObservableCollection<SubId> SubIds { get; set; } = new ObservableCollection<SubId>();
private MainId mainId;
public MainId SelectedMainId
{
get { return mainId; }
set { SetProperty(ref mainId, value); }
}
private SubId selectedId;
public SubId SelectedId
{
get { return selectedId; }
set { SetProperty(ref selectedId, value); }
}
}
public class MainId : BindableBase
{
private string name;
public string Name
{
get { return name; }
set
{
SetProperty(ref name, value);
}
}
public List<SubId> SubIds { get; set; } = new List<SubId>();
}
public class SubId : BindableBase
{
private string name;
public string Name
{
get { return name; }
set { SetProperty(ref name, value); }
}
}
The MainWindow.xaml
<Window x:Class="CascadingComboBox.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:CascadingComboBox"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel Margin="30">
<ComboBox Margin="5" Width="150"
ItemsSource="{Binding MainIds}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedMainId}"
SelectionChanged="ComboBox_SelectionChanged"/>
<ComboBox Margin="5" Width="150"
ItemsSource="{Binding SubIds}"
SelectedItem="{Binding SelectedId}"
DisplayMemberPath="Name"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10">
<Button Margin="5" Width="50" Content="Save" Click="SaveButtton_Click" />
<Button Margin="5" Width="50" Content="Load" Click="LoadButton_Click"/>
</StackPanel>
</StackPanel>
</Window>
During serialization, SelectedItem contains an object from ComboBoxItems collection.
But after deserialization this is no longer true: now SelectedItem is a new instance, even though it has same content as one of the items in ComboBoxItems. This is how Json.NET works by default.
You can fix that by changing PreserveReferencesHandling option like this:
var jsonSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };
JsonConvert.SerializeObject(model, Formatting.Indented, jsonSettings);
...
model = JsonConvert.DeserializeObject<List<Person>>(json, jsonSettings);
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_PreserveReferencesHandling.htm

assign click event to a Button in a DataTemplate

<Window x:Class="WpfApp12.MainWindow"
xmlns=...usual namespaces...
Loaded="Window_Loaded"
>
<Window.Resources>
<DataTemplate x:Key="myHeaderTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{TemplateBinding Content}"/>
<Button Margin="5,0,0,0" x:Name="MyButton">Press me</Button>
</StackPanel>
</DataTemplate>
</Window.Resources>
<!-- Just point the datacontext to the code behind -->
<Window.DataContext>
<Binding RelativeSource="{RelativeSource Mode=Self}"/>
</Window.DataContext>
<DataGrid Name="DG" ItemsSource="{Binding People}"/>
</Window>
This, togheter with the code behind below gives just what I want: a DataGrid with a column whose header has been dynamically assigned a DataTemplate with a Button "Press me":
The code behind:
public partial class MainWindow : Window
{
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}
public MainWindow()
{
People.Add(new Person() { Name = "Isaac", Surname = "Newton" });
People.Add(new Person() { Name = "Galileo", Surname = "Galilei" });
InitializeComponent();
}
public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DG.Columns[0].HeaderTemplate = (DataTemplate)FindResource("myHeaderTemplate");
//how to access the button in the template in order to assign the click event?
}
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//DO SOMETHING
}
}
}
Now i want to dynamically wire MyButton_Click event to the button in the template.
This kind of problems seem to have a lot of coverage, this one being one of the best:
WPF How to access control from DataTemplate
There there is something like:
ComboBox myCombo = _contentPresenter.ContentTemplate.FindName("myCombo", _contentPresenter) as ComboBox;
I'm not very familiar with the templating, and I cannot find the starting point, the "content presenter" on which to call the FindName.
You could use a recursive helper method that finds the Button in the visual tree:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DG.Columns[0].HeaderTemplate = (DataTemplate)FindResource("myHeaderTemplate");
DG.Dispatcher.BeginInvoke(new Action(() =>
{
DataGridColumnHeadersPresenter presenter = FindVisualChild<DataGridColumnHeadersPresenter>(DG);
DataGridCellsPanel dataGridCellsPanel = FindVisualChild<DataGridCellsPanel>(presenter);
DataGridColumnHeader header = dataGridCellsPanel.Children[0] as DataGridColumnHeader;
Button button = FindVisualChild<Button>(header);
if (button != null)
button.Click += MyButton_Click;
}));
}
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//DO SOMETHING
}
private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}

Get checked items from a listbox

I'm just getting used to MVVM and want to do without the code-behind and define everything in the view-models.
the combobox represents several selection options (works). I would like to query the elements that have been checked.
Unfortunately I can't access them. The textbox should display all selected elements as concatenated string.
View-Model
class MainViewModel : BaseViewModel
{
#region Fields
private ObservableCollection<EssayTypeViewModel> _essayTypes;
private EssayTypeViewModel _selectedEssayTypes;
#endregion
public ObservableCollection<EssayTypeViewModel> EssayTypes
{
get => _essayTypes;
set
{
if (_essayTypes == value) return;
_essayTypes = value; OnPropertyChanged("EssayTypes");
}
}
public EssayTypeViewModel SelectedEssayTypes
{
get => _selectedEssayTypes;
set { _selectedEssayTypes = value; OnPropertyChanged("SelectedEssayTypes"); }
}
public MainViewModel()
{
// Load Essay Types
EssayTypeRepository essayTypeRepository = new EssayTypeRepository();
var essayTypes = essayTypeRepository.GetEssayTypes();
var essayTypeViewModels = essayTypes.Select(m => new EssayTypeViewModel()
{
Text = m.Text
});
EssayTypes = new ObservableCollection<EssayTypeViewModel>(essayTypeViewModels);
}
}
XAML
<ListBox x:Name="Listitems" SelectionMode="Multiple" Height="75" Width="200" ItemsSource="{Binding EssayTypes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Text}" IsChecked="{Binding Checked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Text="{Binding Path=SelectedEssayTypes}" Grid.Column="0" Width="160" Height="25" Margin="0,140,0,0"/>
You could hook up an event handler to the PropertyChanged event of all EssayTypeViewModel objects in the EssayTypes collection and raise the PropertyChanged event for a read-only property of the MainViewModel that returns all selected elements as concatenated string:
public MainViewModel()
{
// Load Essay Types
EssayTypeRepository essayTypeRepository = new EssayTypeRepository();
var essayTypes = essayTypeRepository.GetEssayTypes();
var essayTypeViewModels = essayTypes.Select(m =>
{
var vm = EssayTypeViewModel()
{
Text = m.Text
};
vm.PropertyChanged += OnPropertyChanged;
return vm;
});
EssayTypes = new ObservableCollection<EssayTypeViewModel>(essayTypeViewModels);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Checked")
OnPropertyChanged("SelectedItems");
}
public string SelectedItems => string.Join(",", EssayTypes.Where(x => x.Checked).ToArray());
This requires the EssayTypeViewModel class to implement the INotifyPropertyChanged interface (by for example deriving from your BaseViewModel class).
You can apply Mode = Two way on the checkbox binding.
<CheckBox Content="{Binding Text}" IsChecked="{Binding Checked, Mode=TwoWay}"/>
then you can iterate through the essay types collection to check if the item entry was checked.
For ex. Sample code can be:
foreach (var essayTypeInstance in EssayTypes)
{
if(essayTypeInstance.Checked)
{
// this value is selected
}
}
Hope this helps.
mm8 answer works. In the meantime i came up with another approach. Not 100% MVVM compatible but it works and is quite simple.
XAML
<ListBox x:Name="ListItems" SelectionMode="Multiple" Height="75" Width="200" ItemsSource="{Binding CollectionOfItems}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Checked, Mode=TwoWay}" Unchecked="GetCheckedElements" Checked="GetCheckedElements" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Text="{Binding SelectedItemsString, UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" Width="160" Height="25" Margin="0,140,0,0"/>
Code Behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
private void GetCheckedElements(object sender, RoutedEventArgs e)
{
(DataContext as MainViewModel)?.FindCheckedItems();
(DataContext as MainViewModel)?.ConcatSelectedElements();
}
}
Model
public class Items
{
public bool Checked { get; set; }
public string Name { get; set; }
}
ItemsViewModel (BaseViewModel only implements INotifyPropertyChanged)
class ItemsViewModel : BaseViewModel
{
private bool _checked;
private string _name;
public bool Checked
{
get => _checked;
set
{
if (value == _checked) return;
_checked = value;
OnPropertyChanged("Checked");
}
}
public string Name
{
get => _name;
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}
}
MainViewModel
public class MainViewModel : BaseViewModel
{
private string _selectedItemsString;
private ObservableCollection<Items> _selectedItems;
public ObservableCollection<Items> CollectionOfItems { get; set; }
public ObservableCollection<Items> SelectedItems
{
get => _selectedItems;
set
{
_selectedItems = value;
OnPropertyChanged("SelectedItems");
}
}
public string SelectedItemsString
{
get => _selectedItemsString;
set
{
if (value == _selectedItemsString) return;
_selectedItemsString = value;
OnPropertyChanged("SelectedItemsString");
}
}
public MainViewModel()
{
CollectionOfItems = new ObservableCollection<Items>();
SelectedItems = new ObservableCollection<Items>();
CollectionOfItems.Add(new Items { Checked = false, Name = "Item 1" });
CollectionOfItems.Add(new Items { Checked = false, Name = "Item 2" });
CollectionOfItems.Add(new Items { Checked = false, Name = "Item 3" });
}
public void FindCheckedItems()
{
CollectionOfItems.Where(x => x.Checked).ToList().ForEach(y => SelectedItems.Add(y));
}
public void ConcatSelectedElements()
{
SelectedItemsString = string.Join(", ", CollectionOfItems.Where(x => x.Checked).ToList().Select(x => x.Name)).Trim();
}
}

How do I properly set my itemsource in WPF to display my ObservableCollection items?

I have this project where I am trying to figure out how to add things to the listview and then later be able to delete them. But I cant seem to get the itemsource to bind unless I hardcode it. How do I do it in the XAML?
This adds a item to the listview
public partial class MainWindow : Window
{
private ObservableCollection<myItem> Item;
const string pattern = #"((.*)) (.*) left the game";
public MainWindow()
{
InitializeComponent();
}
private void btnAppend_Click(object sender, RoutedEventArgs e)
{
Item = new ObservableCollection<myItem>() { new myItem() { Username = "Prabhat" } };
lvUsers.ItemsSource = Item;
}
}
However if I remove the hardcoded itemsource it doesnt add it even if I add Itemsource={Binding Item} to ym XAML
<Grid>
<ListView Name="lvUsers" ItemsSource="{Binding Item}" HorizontalAlignment="Left" Height="107" Margin="10,10,0,0" VerticalAlignment="Top" Width="497">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="100" DisplayMemberBinding="{Binding Username}"/>
</GridView>
</ListView.View>
</ListView>
<TextBox Name="tbConent" HorizontalAlignment="Left" Height="78" Margin="10,122,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="497"/>
<Button Name="btnAppend" Click="btnAppend_Click" Content="Append" HorizontalAlignment="Left" Margin="213,220,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
EDIT
Class
public class myItem
{
public string Username { get; set; }
}
EDIT 2
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.Windows;
namespace Listviewssssssssssssss
{
public partial class MainWindow : Window
{
public ObservableCollection<myItem> Item { get; private set; }
public MainWindow()
{
InitializeComponent();
}
private void btnAppend_Click(object sender, RoutedEventArgs e)
{
Item = new ObservableCollection<myItem>() { new myItem() { Username = "Prabhat" } };
lvUsers.Items.Refresh();
}
private void btnRemove_Click(object sender, RoutedEventArgs e)
{
}
}
}
Make Item a public property:
public ObservableCollection<myItem> Item { get; private set; }
And you can bind to it like this:
<ListView Name="lvUsers" ItemsSource="{Binding Item, RelativeSource={RelativeSource AncestorType=Window}}" ...>
Make sure that myItem is a public type:
public class myItem { ... }
Or you could set the DataContext of the window to itself:
public partial class MainWindow : Window
{
public ObservableCollection<myItem> Item { get; private set; }
const string pattern = #"((.*)) (.*) left the game";
public MainWindow()
{
InitializeComponent();
DataContext = this;
Item = new ObservableCollection<myItem>() { new myItem() { Username = "Prabhat" } };
}
}
...and bind to the source collection directly:
<ListView Name="lvUsers" ItemsSource="{Binding Item}" ...>
You should also probably consider renaming the property to "Items" since it is a collection.
Edit:
Edit: If you intend to set the Item property dynamically after the initial binding, you also need to implement the INotifyPropertyChanged interface and raise change notifications:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<myItem> _items;
public ObservableCollection<myItem> Item
{
get { return _items; }
set { _items = value; NotifyPropertyChanged(); }
}
public MainWindow()
{
InitializeComponent();
}
private void btnAppend_Click(object sender, RoutedEventArgs e)
{
Item = new ObservableCollection<myItem>() { new myItem() { Username = "Prabhat" } };
}
private void btnRemove_Click(object sender, RoutedEventArgs e)
{
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Categories

Resources