When item on my ListView is clicked I want to make another one of different template to appear below it. I have defined templates in Window.Resources and I thought about changing ItemTemplate when item is clicked, adding new item and changing it to default template, but i am using list with my ListView as ItemsSource it showed only one template and only because (for now) both of them are the same in bindings. What should i do?
Code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<TransactionItem> item = new List<TransactionItem>();
item.Add(new TransactionItem() { category="Deska", index="2", name="Topielec"});
List<object> transactions = new List<object>();
transactions.Add(new Transaction() { name = "Maciek", surname = "Chludzinski", begin = "Dzisiaj 20:14", end = "Dzisiaj 21:14", price = "240 zł", remain = "42 minuty", items = item });
obMainListBinding.ItemTemplate = (DataTemplate)this.FindResource("LessClientTemplate");
MessageBox.Show(obMainListBinding.ItemTemplate.DataTemplateKey.ToString());
transactions.Insert(1, new Transaction() { name = "jhadf", surname = "Chludzhadfi", begin = "Dhad:14", end = "Dzisiajah", price = "240 zł", remain = "42 minuty"});
obMainListBinding.ItemTemplate = (DataTemplate)this.FindResource("BasicTransactionTemplate");
obMainListBinding.ItemsSource = transactions;
}
public class Transaction
{
public string name { get; set; }
public string surname { get; set; }
public string begin { get; set; }
public string end { get; set; }
public string remain { get; set; }
public string price { get; set; }
public List<TransactionItem> items { get; set; }
}
public class TransactionItem
{
public string category { get; set; }
public string index { get; set; }
public string name { get;set; }
}
public class LessTransaction
{
public string name { get; set; }
public string surname { get; set; }
public string begin { get; set; }
public string end { get; set; }
public string remain { get; set; }
public string price { get; set; }
}
}
XAML:
<Window
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" mc:Ignorable="d" x:Class="SurfManager.MainWindow"
Title="MainWindow" Height="524.5" Width="1078">
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
</Window.Triggers>
<Window.Resources>
<DataTemplate x:Key="BasicTransactionTemplate">
<Grid MaxHeight="50">
<Grid.RowDefinitions>
<RowDefinition Height="41*"/>
<RowDefinition Height="42*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="192*"/>
<ColumnDefinition Width="234*"/>
<ColumnDefinition Width="189*"/>
<ColumnDefinition Width="443*"/>
</Grid.ColumnDefinitions>
<Label Name="Name" Content="{Binding name}" Grid.RowSpan="1" Grid.Column="1" Grid.ColumnSpan="1" />
<Label Name="Surname" Content="{Binding surname}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1"/>
<Label Name="Begin" Content="{Binding begin}" Grid.Column="2"/>
<Label Name="End" Content="{Binding end}" Grid.Row="1" Grid.Column="2"/>
<Label Name="Remain" Content="{Binding remain}" Grid.Column="3"/>
<Label Name="Price" Content="{Binding price}" Grid.Row="1" Grid.Column="3"/>
<ListView Name="lvItems" ItemsSource="{Binding items}" Grid.Column="4" Grid.RowSpan="2">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding category}" />
<TextBlock Text=", Nr" />
<TextBlock Text="{Binding index}" />
<TextBlock Text="{Binding name}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
<DataTemplate x:Key="LessClientTemplate">
<Grid MaxHeight="50">
<Grid.RowDefinitions>
<RowDefinition Height="41*"/>
<RowDefinition Height="42*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="192*"/>
<ColumnDefinition Width="234*"/>
<ColumnDefinition Width="189*"/>
<ColumnDefinition Width="443*"/>
</Grid.ColumnDefinitions>
<Label Name="Name" Content="{Binding name}" Grid.RowSpan="1" Grid.Column="1" Grid.ColumnSpan="1" />
<Label Name="Surname" Content="{Binding surname}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1"/>
<Label Name="Begin" Content="{Binding begin}" Grid.Column="2"/>
<Button Name="End" Content="{Binding end}" Grid.Row="1" Grid.Column="2"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl>
<TabItem Header="Obecne Wypożyczenia" Background="#FFF40AFF" Foreground="Black" BorderBrush="#FF8C8E94" OpacityMask="White">
<Grid Background="#FFE5E5E5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<ListView Name="obMainListBinding" BorderThickness="0" ItemTemplate="{StaticResource BasicTransactionTemplate}">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
</ListView>
</Grid>
</TabItem>
<TabItem Header="Baza Klientow">
<Grid Background="#FFE5E5E5">
<ListView BorderThickness="0" >
<ListViewItem Height="66" Background="Red">
<Grid Background="Black" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="0*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0*"/>
<RowDefinition Height="0*"/>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
</Grid>
</ListViewItem>
</ListView>
</Grid>
</TabItem>
<TabItem Header="TabItem" HorizontalAlignment="Left" Height="35.293" VerticalAlignment="Top" Width="57.32" Margin="-2,-2,0,-13.333">
<Button Content="Button" Height="100" Margin="430,174,430,173"/>
</TabItem>
</TabControl>
You could try to use the ItemTemplateSelector property:
How do I use a ItemTemplateSelector together with a HeaderTemplate in a WPF ListView?
and(or) triggers that change Template:
How to change control template from Style.Triggers
EDIT
To use TemplateSelector you could add some dummy property on your items(or wrap them) that will allow you to discern new item from old.
...
public Int32 Generation
{
get ...
}
public class GenerationTypeSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var transaction = (TransactionItem)item;
if (transaction .Generation == 0)
return Gen0Template;
else
return Gen1Template;
}
}
Related
I have a WPF form that I want to use to manipulate a database table. To get the data out of the database I use Entity Framework Core. I try to follow the MVVM pattern.
So I have a Model called Employee with a number of string properties like Firstname and so on.
The form has a ListView that shows an ObservableCollection of Employee. Further I have a number of TextBoxes to display and manipulate the properties of single Employee objects. The selectedMemberPath of the ListView is bound to a property SelectedEmployee. The setter of SelectedEmployee than copies it's own properties to EditedEmployee. The TextBoxes are bound to EditedEmployee. The idea is, that I don't want to directly edit the ObservableCollection. This should only happen if a save button is clicked.
This is my view model.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using XdcCore.Models;
using XdcCore.ViewModels.Commands;
namespace XdcCore.ViewModels
{
class EmployeeEditorVM : List<Employee>, INotifyPropertyChanged
{
public EmployeeSaveCommand EmployeeSaveCommand { get; set; }
public EmployeeEditorVM()
{
EmployeeSearch();
EmployeeSaveCommand = new EmployeeSaveCommand(this);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string employeeSearchText;
public string EmployeeSearchText
{
get { return employeeSearchText; }
set
{
employeeSearchText = value;
OnPropertyChanged("EmployeeSearch");
EmployeeSearch();
}
}
private Employee selectedEmployee;
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
EditedEmployee = SelectedEmployee;
}
}
private Employee editedEmployee;
public Employee EditedEmployee
{
get { return editedEmployee; }
set
{
editedEmployee = value;
OnPropertyChanged("EditedEmployee");
}
}
private ObservableCollection<Employee> employees;
public ObservableCollection<Employee> Employees
{
get { return employees; }
set
{
employees = value;
OnPropertyChanged("Employees");
}
}
public void EmployeeSearch()
{
using (var context = new XdcContext())
{
if (employeeSearchText != null)
{
var _employees = context.Employee
.Where(x => x.Firstname.Contains(employeeSearchText));
Employees = new ObservableCollection<Employee>(_employees);
}
else
{
var _employees = context.Employee.Select(x => x);
Employees = new ObservableCollection<Employee>(_employees);
}
}
}
public void EmployeeSave()
{
using (var context = new XdcContext())
{
var entity = context.Employee.First(x => x.IdEmployee == SelectedEmployee.IdEmployee);
{
entity.Firstname = SelectedEmployee.Firstname;
entity.Lastname = SelectedEmployee.Lastname;
entity.Initials = SelectedEmployee.Initials;
context.SaveChanges();
}
EmployeeSearch();
}
}
}
}
this is my View:
<Window
x:Class="XdcCore.Views.Editors.EmployeeEditor"
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:local="clr-namespace:XdcCore.Views.Editors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:XdcCore.ViewModels"
Title="Employee"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<vm:EmployeeEditorVM x:Key="vm" />
</Window.Resources>
<Grid DataContext="{StaticResource vm}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="115*" />
<ColumnDefinition Width="277*" />
</Grid.ColumnDefinitions>
<!-- left column -->
<Border BorderBrush="DarkGray" BorderThickness="1">
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="aUTO" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="3,3,3,3"
Content="Filter:" />
<TextBox
x:Name="TextBoxSearch"
Grid.Row="1"
Height="25"
Margin="3,0,3,3"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EmployeeSearchText, Mode=TwoWay}" />
<ListView
x:Name="ListViewOverview"
Grid.Row="2"
Margin="3,0,3,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding Employees, Mode=OneWay}"
SelectedItem="{Binding SelectedEmployee, Mode=OneWayToSource}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Initials}" />
<TextBlock Text=" : " />
<TextBlock Text="{Binding Firstname}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding Lastname}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="ButtonDelete"
Grid.Column="0"
Height="25"
Margin="3,3,3,3"
Content="Delete"
IsEnabled="False" />
<Button
x:Name="ButtonNew"
Grid.Column="1"
Height="25"
Margin="3,3,3,3"
Content="Add New ..."
IsEnabled="True" />
</Grid>
</Grid>
</Border>
<!-- right Column -->
<Grid Grid.Column="1" Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- right column, first row -->
<Border
Grid.Row="0"
BorderBrush="DarkGray"
BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Right"
Content="First Name" />
<Label
Grid.Row="1"
Grid.Column="0"
HorizontalAlignment="Right"
Content="Last Name" />
<Label
Grid.Row="2"
Grid.Column="0"
HorizontalAlignment="Right"
Content="Initials" />
<Label
Grid.Row="3"
Grid.Column="0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="ID" />
<Label
Grid.Row="4"
Grid.Column="0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="RCU" />
<Label
Grid.Row="5"
Grid.Column="0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="RCT" />
<TextBox
x:Name="TextBoxFirstName"
Grid.Row="0"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EditedEmployee.Firstname, Mode=TwoWay}" />
<TextBox
x:Name="TextBoxLastName"
Grid.Row="1"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EditedEmployee.Lastname, Mode=TwoWay}" />
<TextBox
x:Name="TextBoxInitials"
Grid.Row="2"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EditedEmployee.Initials, Mode=TwoWay}" />
<TextBox
x:Name="TextBoxId"
Grid.Row="3"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
IsReadOnly="True" />
<TextBox
x:Name="TextBoxRCU"
Grid.Row="4"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
IsReadOnly="True" />
<TextBox
x:Name="TextBoxRCT"
Grid.Row="5"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
IsReadOnly="True" />
</Grid>
</Border>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="ButnSave"
Grid.Column="1"
Width="76"
Height="25"
Margin="60,3,60,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Command="{Binding EmployeeSaveCommand}"
Content="Save"
IsEnabled="True" />
</Grid>
<!-- Add new -->
</Grid>
</Grid>
</Grid>
</Window>
In other words: I want to click on an item in the list view, it's details are shown in the text boxes. I can change the text in the text boxes but the changes are not applied to the observable collection (or even database) until I click "save". The problem is, that exactly that happens: when I edit text in the text boxes the changes are also shown in the list view. And I can#t see why.
So, I got the concept of "copy vs point" of a variable wrong.
I had two solutions for my problem.
To my Employee model I added the method Copy:
public partial class Employee
{
public int IdEmployee { get; set; }
public string Initials { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Rcu { get; set; }
public DateTime Rct { get; set; }
public Employee Copy()
{
return (Employee)this.MemberwiseClone();
}
}
Then I Changed my ViewModel so that EditedEmployee is a copy of SelectedEmployee
private Employee selectedEmployee;
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
if (SelectedEmployee != null)
{
EditedEmployee = SelectedEmployee.Copy();
}
}
}
private Employee editedEmployee;
public Employee EditedEmployee
{
get { return editedEmployee; }
set
{
editedEmployee = value;
OnPropertyChanged("EditedEmployee");
}
}
The problem with this approach is, that if I mess around with the database and then need to run Scaffold-DbContext (I prefer the code-first approach of EFC) again, I would have to modify all models again. A solution to that might be some a second, modified Model that inherits from the original Model and then adds the Copy method.
My second approach is to bind the ListView via SelectedIndex instead of SelectedItem.
<ListView
...
ItemsSource="{Binding Employees, Mode=OneWay}"
SelectedIndex="{Binding SelectedItemIndex, Mode=TwoWay}">
In the ViewModel this is then represented by an int property. If this int is set (and >= 0) Employee gets copied EmployeeWorkingCopy. Furthermore if EmployeeWorkingCopy is set a single Employee dubbed EditedEmployee is set as the Employee of the working copy with the selected index.
private int selectedItemIndex;
public int SelectedItemIndex
{
get { return selectedItemIndex; }
set
{
selectedItemIndex = value;
if (SelectedItemIndex >= 0)
EmployeesWorkingCopy = new ObservableCollection<Employee>(Employees);
}
}
private Employee editedEmployee;
public Employee EditedEmployee
{
get { return editedEmployee; }
set
{
editedEmployee = value;
OnPropertyChanged("EditedEmployee");
}
}
private ObservableCollection<Employee> employeesWorkingCopy;
public ObservableCollection<Employee> EmployeesWorkingCopy
{
get { return employeesWorkingCopy; }
set
{
employeesWorkingCopy = value;
EditedEmployee = EmployeesWorkingCopy[SelectedItemIndex];
}
}
Thanks a lot for pointing out my misconception.
I have a Observable Collection, I want to Filter the collection. The Collection class like a dictionary. I have tried the following code But it is not filtering the collection. I know it is very basic question. I am new to c#. I am studying. Please any one help me to filter the collection. I have mentioned the code below, please refer
GroupModel
public class GroupModel
{
public string Key { get; set; }
public ObservableCollection<ValueModel> Values { get; set; }
}
ValueModel
public class ValueModel
{
public int Id { get; set; }
public string Name { get; set; }
}
ViewModel
Public Class ViewModel
{
public ObservableCollection<GroupModel> MainValues
{
get { return mainValues; }
set { mainValues = value; }
}
public string SearchIndicator
{
get { return searchIndicator; }
set
{
searchIndicator = value;
OnPropertyChanged(SearchIndicator);
ItemsView.Refresh();
}
}
public ViewModel(IMainValueCollection mainValueCollection)
{
MainValue = new ObservableCollection<GroupModel>();
this.MainValue = mainValueCollection;
ItemsView.Filter = new Predicate<object>(o => Filter(o as ValueModel));
}
public ICollectionView ItemsView
{
get
{
var value = (MainValues.SelectMany(a => a.Values)).ToList();
return CollectionViewSource.GetDefaultView((MainValues.SelectMany(a => a.Values)));
}
}
private bool Filter(ValueModel value)
{
if (SearchIndicator == null)
{
return true;
}
return value.Name.IndexOf(SearchIndicator, StringComparison.OrdinalIgnoreCase) != -1;
}
}
MainViewUI
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
Height="35"
Margin="5,5,0,5">
<Border
Margin="10,10,10,0"
Padding="1"
BorderBrush="LightGray"
BorderThickness="1"
CornerRadius="0">
<Grid
Height="30"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid
Grid.Row="0"
Grid.Column="0"
Margin="2,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Image
Width="25"
Height="25"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="/Images/SearchIcon.png" />
</Grid>
<Grid
Name="TextBlockGrid"
Grid.Row="0"
Grid.Column="1"
Height="30"
HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Padding="5,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Foreground="Gray"
Text="Search">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource MultiStringToVisibilityConverter}">
<Binding ElementName="searchBox" Path="Text.IsEmpty" />
<Binding ElementName="searchBox" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBox
x:Name="searchBox"
Width="{Binding ActualWidth, ElementName=TextBlockGrid}"
Padding="5,0,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
Text="{Binding SearchIndicator, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Grid>
</Border>
</Grid>
<ItemsControl
Grid.Row="1"
MinWidth="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="White"
BorderThickness="0"
ItemsSource="{Binding MainValues, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<Grid>
<TextBlock x:Name="keys" Text="{Binding Key}" />
</Grid>
</Expander.Header>
<ListBox
Margin="15,0,0,0"
BorderThickness="0"
DisplayMemberPath="Name"
ItemsSource="{Binding Values}" />
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
You are not binding to ItemsView at all.
Replace
ItemsSource="{Binding MainValues, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
with
ItemsSource="{Binding ItemsView}">
Also change the ItemsView implementation to
public ICollectionView ItemsView
{
get { return CollectionViewSource.GetDefaultView(MainValues); }
}
Try to create simple app that will add items to the list. Have problems with binding entries with properties in ViewModel.
Here is my xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:MyScoreDemo.ViewModels;assembly=MyScoreDemo"
x:Class="MyScoreDemo.Views.ClubListPage">
<StackLayout
Padding="15"
Spacing="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Name:" Grid.Row="0" Grid.Column="0"/>
<Entry x:Name="EntryName" Text="{Binding Club.Name, Mode=OneWayToSource}" Grid.Row="0" Grid.Column="1"/>
<Label Text="Country:" Grid.Row="1" Grid.Column="0"/>
<Entry x:Name="EntryCountry" Text="{Binding Club.Country, Mode=OneWayToSource}" Grid.Row="1" Grid.Column="1"/>
<Button Text="Add" Command="{Binding AddCommand}" CommandParameter="{x:Reference EntryName}"
Grid.Row="2" Grid.ColumnSpan="2" Grid.Column="0" />
</Grid>
<ListView ItemsSource="{Binding Clubs}"
Margin="5">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Path=Name}"/>
<Label Text="{Binding Path=Country}" Grid.Column="1"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout.BindingContext>
<viewModels:ClubListViewModel/>
</StackLayout.BindingContext>
</StackLayout>
And ViewModel code:
private Club _club;
public ICommand AddCommand { get; set; }
public ICommand RemoveCommand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Club> Clubs { get; set; }
public ClubListViewModel()
{
AddCommand = new Command(AddClub);
RemoveCommand = new Command(RemoveClub);
Clubs = new ObservableCollection<Club>();
}
public Club Club
{
get => _club;
set
{
_club = value;
OnPropertyChanged("Club");
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//Commands
private void AddClub()
{
}
Set breakpoints in property`s Club set section and try different modes, but it never stops.
All that I need to change is ta add Club = new Club(); in constructor of my ViewModel class.
I am using the folloowing class but its not allowing me to display show_times in my xaml its just comming up
popcornpk.datamodel.fetchtiming
public class FetchTiming
{
public string id { get; set; }
public string theater_name { get; set; }
public string address { get; set; }
public List<string> show_times { get; set; }
public string screen_id { get; set; }
public string title { get; set; }
}
public class MovieDetail
{
public MovieDetails movie_details { get; set; }
public List<FetchTiming> fetch_timing { get; set; }
}
My Class call
public async Task<MovieDetail> GetMovieShowtimesAsync()
{
string jsonresult = await WCFRESTServiceCall("GET", "movie_details");
var jarray = JsonConvert.DeserializeObject<MovieDetail>(jsonresult);
return jarray;
}
This is my xamlmethod call I hav eno idea what is going on the data is being returned ok but I just cant seem to dispaly it
private async void listViewShowtimes_Loaded(object sender, RoutedEventArgs e)
{
popcornpk_Dal _dal = new popcornpk_Dal();
MovieDetail _showTimes = await _dal.GetMovieShowtimesAsync();
var listView = (ListView)sender;
listView.ItemsSource = _showTimes.fetch_timing.ToList();
}
Xaml Of DataTemplate
<PivotItem x:Name="pvtShowTimes" Header="showtimes">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListView x:Name="listViewShowtimes" ItemsSource="{Binding}" Loaded="listViewShowtimes_Loaded">
<DataTemplate>
<StackPanel Height="505">
<TextBlock FontSize="13" x:Name="txtshowtime" Text="{Binding theater_name}" HorizontalAlignment="Left" Margin="19,223,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" SelectionChanged="txtTtile_SelectionChanged"/>
<TextBlock FontSize="13" x:Name="txtshow_times" Text="{Binding address}" HorizontalAlignment="Left" Margin="19,223,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" SelectionChanged="txtTtile_SelectionChanged"/>
</StackPanel>
</DataTemplate>
</ListView>
</Grid>
</PivotItem>
Below is a screen shot of the app running on the device any help be greatly apreciated.
Ok So i have it at least displaying the thertre name which is good on the show times screen but its still not allowing me to display the show_times field.
<ListView x:Name="listViewShowtimes" ItemsSource="{Binding}" Loaded="listViewShowtimes_Loaded">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock FontSize="13" Grid.Row="0" Grid.Column="0" x:Name="txtshowtime" Text="{Binding theater_name}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" />
<TextBlock FontSize="13" Grid.Row="1" Grid.Column="0" x:Name="txtshow_times" Text="{Binding show_times}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I think what i need to no is how to bind a list of strings through xaml Problem I have i need the show times to appear below the cinema name you see their
You have Text="{Binding show_times}" so In your class FetchTiming,
public List<string> show_times { get; set; }
is a list so if you bind it to a TextBlock, it will simply do ToString(). You have to add inside the template another ListView like:
<TextBlock FontSize="13" Grid.Row="0" Grid.Column="0" x:Name="txtshowtime" Text="{Binding theater_name}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" />
<ListView ItemsSource={Binding show_times} />
And will do the trick.
I'm trying to find a way to display a horizontal List of items in WPF, the trick is that the Window which contains the List will be displayed on various screen sizes and all the items in the list need to be resized to fill the available space without any use of scroll bars.
I've found that a ViewBox control can be used to achieve the desired affect, but the ViewBox works only if I set <RowDefinition Height="300"/>.This approach doesn't work because if you have a certain number of items in the List they start becoming cut off.
If I remove <RowDefinition Height="300"/> then the first item in the list fills the screen and the rest are cut off
Any suggestions on how I can make all the items in the list resize to fill the available space no matter what the screen resolution is?
XAML:
<Window x:Class="ViewBoxExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowState="Maximized">
<ItemsControl ItemsSource="{Binding Path=Employees}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="300"/>
</Grid.RowDefinitions>
<Viewbox Grid.Row="0" Grid.Column="0">
<TextBlock Text="{Binding Path=Name}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="1">
<TextBlock Text="{Binding Path=Surname}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="2">
<TextBlock Text="{Binding Path=Age}" />
</Viewbox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
C#:
using System.Collections.Generic;
using System.Windows;
namespace ViewBoxExample
{
public partial class MainWindow : Window
{
public List<Employee> _employees = new List<Employee>();
public List<Employee> Employees
{
get { return _employees; }
set { _employees = value; }
}
public MainWindow()
{
InitializeComponent();
Employees = new List<Employee>()
{
new Employee{ Name="Name1",Surname="Surname1",Age=20},
new Employee{ Name="Name2",Surname="Surname2",Age=30},
new Employee{ Name="Name3",Surname="Surname3",Age=40},
new Employee{ Name="Name4",Surname="Surname4",Age=50},
new Employee{ Name="Name5",Surname="Surname5",Age=60},
};
this.DataContext = this;
}
}
public class Employee
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
}
}
Just put your ItemsControl in ViewBox
<Viewbox>
<ItemsControl ItemsSource="{Binding Path=Employees}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Viewbox Grid.Row="0" Grid.Column="0">
<TextBlock Text="{Binding Path=Name}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="1">
<TextBlock Text="{Binding Path=Surname}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="2">
<TextBlock Text="{Binding Path=Age}" />
</Viewbox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>
EDIT: if i am doing the same type of thing i would use the actual Height and Width approach as explained by Kent Boogaart in this Answer