I have listview that binding with observable Collection, this listview show the invoice items, any item in invoice maybe has a sub detail (Options), (for example item color),
what i want to ask about is: how to make list view show the item options as list under the main item in listview, i hope my question is clear .. for more clarity look at the image :
What i want is in a yellow color, how to make listview look like the image ?
here's my invoice listview code :
<ListView x:Name="temsReceipt" ItemsSource="{Binding ocItemsReceipt}">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Height="40" Width="50"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Item Name" Width="230" DisplayMemberBinding="{Binding ItemName}"/>
<GridViewColumn Header="Item Price" Width="100" DisplayMemberBinding="{Binding ItemPrice}"/>
</GridView>
</ListView.View>
The same think if i used the datagrid
Let's say that you have following classes:
class InvoiceItem
{
public string ItemName { get; set; }
public List<InvoiceOption> Options { get; set; }
}
class InvoiceOption
{
public string OptionName { get; set; }
}
ListView solution:
<ListView x:Name="temsReceipt" ItemsSource="{Binding}">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Height="40" Width="50"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Item Name" Width="230" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding ItemName}" VerticalAlignment="Center"
FontWeight="Bold" FontSize="18"/>
<ListBox ItemsSource="{Binding Options}" Grid.Row="1" Background="Yellow"
HorizontalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding OptionName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Item Price" Width="100" DisplayMemberBinding="{Binding ItemPrice}"/>
</GridView>
</ListView.View>
</ListView>
If you want to use DataGrid you can use RowDetailsTemplate:
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding ItemName}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel Margin="2" Background="Yellow">
<TextBlock Text="Options:" />
<ListBox ItemsSource="{Binding Options}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding OptionName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
Sample data:
...
public MainWindow()
{
InitializeComponent();
List<InvoiceItem> _source = new List<InvoiceItem>
{
new InvoiceItem
{
ItemName = "Item1",
Options = new List<InvoiceOption>
{
new InvoiceOption { OptionName = "Option1" },
new InvoiceOption { OptionName = "Option2" }
}
},
new InvoiceItem
{
ItemName = "Item2",
Options = new List<InvoiceOption>
{
new InvoiceOption { OptionName = "Option3" },
new InvoiceOption { OptionName = "Option4" }
}
}
};
this.DataContext = _source;
}
...
ListView result:
Related
I have a wpf MVVM application which shows a DataGrid. I have a few columns that are DataGridTextColumns and I want another column to be a MultiSelect Combobox in which shows a checkbox and textblock on each row. The dataSource for the datagrid is different than that of the multiselect combobox I am working towards. My Issue is that I cannot see data (list) in the multiselect combobox when its in the datagrid cell. When I move the code outside of the datagrid I am able to see data. This is my code below
ViewModel:
public class TripInfo : ViewModelBase
{
public TripInfo(bool isVisited, string cityName)
{
IsVisited = isVisited;
CityName = cityName;
}
public Boolean IsVisited { get; set; }
public String CityName { get; set; }
}
public class DataGridViewModel : ViewModelBase
{
ObservableCollection<RecordInfo> infos;
List<TripInfo> tripinfos;
ICommand _command;
public ObservableCollection<RecordInfo> PersonsInfo
{
get
{
return infos;
}
set
{
infos = value;
OnPropertyChanged("PersonsInfo");
}
}
public List<TripInfo> TripsInfo
{
get
{
return tripinfos;
}
set
{
tripinfos = value;
OnPropertyChanged("TripsInfo");
}
}
public DataGridViewModel()
{
PersonsInfo = new ObservableCollection<RecordInfo>();
TripsInfo = new List<TripInfo>();
TripsInfo.Add(new TripInfo(false, "Miami"));
TripsInfo.Add(new TripInfo(true, "Boston"));
TripsInfo.Add(new TripInfo(true, "Los Angeles"));
TripsInfo.Add(new TripInfo(true, "Houston"));
TripsInfo.Add(new TripInfo(false, "Dallas"));
TripsInfo.Add(new TripInfo(false, "Atlantic City"));
TripsInfo.Add(new TripInfo(true, "Chicago"));
GetPersonInfoData();
}
private void GetPersonInfoData()
{
PersonsInfo.Add(new RecordInfo
{
Name = "AA",
Age = 24,
DateOfBirth = new DateTime(1987, 4, 29),
Address = "XXX XXX XXXX"
});
PersonsInfo.Add(new RecordInfo
{
Name = "BB",
Age = 23,
DateOfBirth = new DateTime(1988, 3, 4),
Address = "XXX XXXXX XXX"
});
PersonsInfo.Add(new RecordInfo
{
Name = "CC",
Age = 26,
DateOfBirth = new DateTime(1985, 10, 2),
Address = "XXX XXX X"
});
View.Xaml
<Window.Resources>
<Style x:Key="NameCellStyle" TargetType="DataGridCell">
<Style.Setters>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
<Setter Property="Background" Value="Aqua"/>
</Style.Setters>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Name="cmb" Margin="5" Height="20" ItemsSource="{Binding TripsInfo}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Margin="5" IsChecked="{Binding IsVisited}"/>
<TextBlock Margin="5" Text="{Binding CityName}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<DataGrid Grid.Row="1" Name="DGVPersonInfo" ItemsSource="{Binding PersonsInfo}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Button Content="Remove..." Margin="3"
Command="{Binding Path=DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
CommandParameter="{Binding}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Name}">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="FrameworkElement.HorizontalAlignment" Value="Center" />
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Age" Binding="{Binding Age}" CellStyle="{StaticResource NameCellStyle}"/>
<DataGridTemplateColumn Header="Date Of Birth">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DateOfBirth}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding DateOfBirth}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Address" Binding="{Binding Address}" />
<DataGridTemplateColumn Header="Template">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding TripsInfo}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsVisited}" Width="20" />
<TextBlock Text="{Binding CityName}" Width="100" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
ItemSource or any property of inside a Template is not directly accessible to the DataGrid's DataContext or any other Other Control or Window.
We need to explicitly provide the data Path.
As per your Xaml Code I am not sure where you have bind your View Model, but as per your Remove Button Command, below is how your Drop Down itemSource must be bind.
<ComboBox ItemsSource="{Binding Path=DataContext.TripsInfo, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
I failed to perform grouping in list view. It shows error code as:
BindingExpression path error: Indicator' property not found on 'object' ''CollectionViewGroupInternal'`.
may I know which part of my code is wrong?
Below is the class code:
Data are pulled from the database.
foreach(string value in getCountry)
{
string[] values = value.Split(',');
string countryname = values[0].ToString();
string indicator = values[1].ToString();
items.Add(new User() { CountryName = countryname, Indicator = indicator });
}
lvUsers.ItemsSource = items;
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("Indicator"); //i expect error is from here
view.GroupDescriptions.Add(groupDescription);
public class User
{
public string CountryName { get; set; }
public string Indicator { get; set; }
}
Below is the XAML CODE:
<ListView Name="lvUsers" FontSize="25" FontFamily="Arial">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn DisplayMemberBinding="{Binding CountryName}" />
<GridViewColumn DisplayMemberBinding="{Binding Indicator}" />
</GridView>
</ListView.View>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" Text="{Binding Indicator}" FontSize="30" FontFamily="Arial" Foreground="Black"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
In the HeaderTemplate, the binding property should be Name rather than Indicator.
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" Text="{Binding Name}" FontSize="30" FontFamily="Arial" Foreground="Black"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
I have a trouble with displaying properties of instance of external class. There is ListView markup:
<ListView
x:Name="transportListView"
SelectionMode="None"
ItemsSource="{Binding MyModel}">
<ListView.ItemTemplate>
<DataTemplate>
<Border Padding="15" HorizontalAlignment="Center" Margin="0,0,0,10" Background="Gray">
<StackPanel Margin="0,0,0,0">
<TextBlock
Text="{Binding ItemName}"
Margin="0,0,0,0"/>
<TextBlock
Text="{Binding ItemCount}"
Margin="0,0,0,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
MyModel is the page property:
...
public ObservableCollection<ExternalClass> MyModel { get; set; }
...
ExternalClass is the class in some referenced library:
namespace Library.Entities
{
public class ExternalClass
{
public string ItemName { get; set; }
public int ItemCount { get; set; }
}
}
So when I run my application I see list items because I set grey color, but ItemName and ItemCount is not displaying, why? I adding items to collection correctly and binding works for internal classes perfectly.
Change your ListView's ItemsSource to ItemsSource="{Binding}". Like this:
<ListView x:Name="transportListView" ItemsSource="{Binding}">
....
Also in the code behind add this.DataContext = MyModel; below the InitializeComponent();:
public Window1()
{
InitializeComponent();
this.DataContext = MyModel;
}
To Use ListView you also need to Define View (GridView) for it:
<ListView ItemsSource="{Binding MyModel}">
<ListView.View>
<GridView>
<GridViewColumn Width="140" Header="Name" DisplayMemberBinding="{Binding ItemName}"/>
<GridViewColumn Width="140" Header="Count" DisplayMemberBinding="{Binding ItemCount}" />
</GridView>
</ListView.View>
</ListView>
If you want to define template for each row then you can use a ListBox instead of ListView:
<ListBox ItemsSource="{Binding MyModel}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Padding="15" HorizontalAlignment="Center" Margin="0,0,0,10" Background="Gray">
<StackPanel Margin="0,0,0,0">
<TextBlock Text="{Binding ItemName}" Margin="0,0,0,0"/>
<TextBlock Text="{Binding ItemCount}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am a new user to c# and WPF and I have a problem to populate a ListView with text and image.
This is my wpf code:
<Grid>
<ListView Name="MyList" Margin="0,0,328.4,-0.2" >
<ListView.View>
<GridView>
<GridViewColumn Header="Rete" DisplayMemberBinding="{Binding Rete}"/>
<GridViewColumn Header="Immagine" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Immagine}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<Image Height="100" Width="100"/>
</ListView>
<Button Content="Button" HorizontalAlignment="Left" Margin="324,83,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
and this is my c# code:
while (r.Read())
{
MyList.Items.Add(new { Rete = r.GetString(0), Immagine = r.GetString(1) });
}
thanks to all i have solved!!! i changed the image path in the databse the code was correct!! :)
This is my xaml code.
<Grid>
<ListView x:Name="ListView1" VirtualizingStackPanel.IsVirtualizing="True" Height="200" ItemsSource="{Binding ListViewItemsCollections}">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn x:Name="GridViewColumnName" Header="Name" Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="Image_GridViewColumnName" Width="100" Height="50" Source="{Binding GridViewColumnName_ImageSource}" />
<Label Content="{Binding GridViewColumnName_LabelContent}" Width="50" Height="100" />
<Label Content="{Binding GridViewColumnName_ID}" Visibility="Hidden" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="GridViewColumnTags" Header="Tags" Width="100" DisplayMemberBinding="{Binding GridViewColumnTags}" />
<GridViewColumn x:Name="GridViewColumnLocation" Header="Location" Width="238" DisplayMemberBinding="{Binding GridViewColumnLocation}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
This is my c# part..
public ObservableCollection<ListViewItemsData> ListViewItemsCollections { get { return _ListViewItemsCollections; } }
ObservableCollection<ListViewItemsData> _ListViewItemsCollections = new ObservableCollection<ListViewItemsData>();
public MainWindow()
{
InitializeComponent();
ListViewItemsCollections.Add(new ListViewItemsData()
{
GridViewColumnName_ImageSource = #"D:\rd\C Sharp\general\StackOverFlowAnswers\WPF\MSD.JPG",
GridViewColumnName_LabelContent = "shanmugharaj"
});
ListView1.ItemsSource = ListViewItemsCollections;
}
public class ListViewItemsData
{
public string GridViewColumnName_ImageSource { get; set; }
public string GridViewColumnName_LabelContent { get; set; }
public string GridViewColumnName_ID { get; set; }
public string GridViewColumnTags { get; set; }
public string GridViewColumnLocation { get; set; }
}
}
I tested with these its working fine..
If my understanding id right this is you need..
I have a ListView with the following code:
<ListView Name="ListView1">
<ListView.View>
<GridView>
<GridViewColumn Header="File" Width="60">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="28" Height="28" Source="{Binding Icon}" Name="img"/>
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Text="{Binding File}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Type" Width="70" DisplayMemberBinding="{Binding Type}"/>
<GridViewColumn Header="Password" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Width="145" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Can someone tell me how can I add items in it during run time and set all the bindings (Icon,File,Type)?
You create a class like:
class MyData
{
public string File { get; set; }
public string Icon { get; set; } // a path to an Icon
...
}
and then you use (in for example Window_Loaded) an
ObservableCollection<MyData> data = new ObservableCollection<MyData>();
listView1.Items = data;
data.Add(new MyData { File="text", ... });