Im trying to bind an ObservableCollection of
public class ProgressInfo : BindableBase, IProgress<Tuple<string, int>>
{
public ProgressInfo()
{
Message = "start";
ProgressBarValue = 50;
}
private string _message;
public string Message
{
get { return _message; }
set { _message = value; OnPropertyChanged(() => Message); }
}
private int _progressBarValue;
public int ProgressBarValue
{
get { return _progressBarValue; }
set { _progressBarValue = value; OnPropertyChanged(() => ProgressBarValue); }
}
public void Report(Tuple<string, int> value)
{
this.Message = value.Item1;
this.ProgressBarValue = value.Item2;
}
}
to WPF Toolkit BusyIndicator with custom content
<xctk:BusyIndicator DisplayAfter="0" IsBusy="{Binding IsBusy, Mode=OneWay}" >
<xctk:BusyIndicator.BusyContentTemplate>
<DataTemplate>
<StackPanel Margin="4">
<TextBlock Text="{x:Static lang:Resources.TRWAIMPORT}" FontWeight="Bold" HorizontalAlignment="Center"/>
<ItemsControl ItemsSource="{Binding ProgressInfos, UpdateSourceTrigger=PropertyChanged}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="4">
<TextBlock Text="{Binding ProgressInfo.Message, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay }"/>
<ProgressBar Value="{Binding Path=ProgressInfo.ProgressBarValue, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Height="15"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>
<xctk:BusyIndicator.ProgressBarStyle>
<Style TargetType="ProgressBar">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</xctk:BusyIndicator.ProgressBarStyle>
Also I'm passing objects from the ObervableCollection to my Tasks so they change their properties through the Report method.
But for some reason the BusyIndicator is never updated with new values and the ObservableCollection seems to always be empty (ItemsControl doesn't produce any items)
What am I doing wrong ? This approach worked on any other control but the BusyIndicator seems it doesn't get it right
Related
Have style for a series of buttons btn1, btn2, btn3, etc.
Inside the style for each button is a TextBlock for displaying the "Content" of the button, (since the border inside the style covers any content of the button itself).
Now, I would like for the TextBlock name to be tied to the button name. For example - btn1's text block's name would be btn1Txt. The purpose of this would be the end user can assign each button its own text in a settings menu.
Any hints on how I would go about this? I admit I'm relatively new to WPF and bindings.
EDIT:::: WHAT I"VE GOT SO FAR THAT IS WORKING.
On load, the program checks the settings file for the Text for each button. Each button's content is assigned the proper information. Then inside the style, I bind the TextBlock Text to the content of the parent button.
This may not be the normal way of going about it, but it works
Method
List<string> MainButtons = Properties.Settings.Default.MainButtonNames.Cast<string>().ToList();
for (int i = 0; i < MainButtons.Count(); i++)
{
string actualNum = Convert.ToString((i + 1));
var MainButtonFinder = (Button)this.FindName("MainButton" + actualNum);
Console.WriteLine(MainButtonFinder.Name);
MainButtonFinder.Content = MainButtons[i];
Console.WriteLine(MainButtonFinder.Content);
}
Style
<Style x:Key="MainButtonStyle" TargetType="{x:Type Button}">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Width" Value="100px"/>
<Setter Property="MinHeight" Value="50"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="20" Height="45" Width="100" Margin="0" Background="#FF99CCFF">
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="LCARS" Foreground="White" Padding="5px" FontSize="18px" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>`
This is the wrong way to go about what you're trying to do. Here's the "right" way to do it. There's a fair amount of boilerplate code here, but you get used to it.
Write a button viewmodel and give your main viewmodel an ObservableCollection of those:
#region ViewModelBase Class
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
#endregion INotifyPropertyChanged
}
#endregion ViewModelBase Class
#region MainViewModel Class
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
ButtonItems.Add(new ButtonItemViewModel("First Command", "First Item", () => MessageBox.Show("First Item Executed")));
ButtonItems.Add(new ButtonItemViewModel("Second Command", "Second Item", () => MessageBox.Show("Second Item Executed")));
}
#region ButtonItems Property
public ObservableCollection<ButtonItemViewModel> ButtonItems { get; }
= new ObservableCollection<ButtonItemViewModel>();
#endregion ButtonItems Property
}
#endregion MainViewModel Class
#region ButtonItemViewModel Class
public class ButtonItemViewModel : ViewModelBase
{
public ButtonItemViewModel(String cmdName, String text, Action cmdAction)
{
CommandName = cmdName;
Text = text;
Command = new DelegateCommand(cmdAction);
}
#region Text Property
private String _text = default(String);
public String Text
{
get { return _text; }
set
{
if (value != _text)
{
_text = value;
OnPropertyChanged();
}
}
}
#endregion Text Property
#region CommandName Property
private String _commandName = default(String);
public String CommandName
{
get { return _commandName; }
private set
{
if (value != _commandName)
{
_commandName = value;
OnPropertyChanged();
}
}
}
#endregion CommandName Property
public ICommand Command { get; private set; }
}
#endregion ButtonItemViewModel Class
public class DelegateCommand : ICommand
{
public DelegateCommand(Action action)
{
_action = action;
}
private Action _action;
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_action?.Invoke();
}
}
Make that MainViewModel the DataContext of your Window:
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
And here's how you can put it all together in the XAML:
<Grid>
<StackPanel Orientation="Vertical">
<GroupBox Header="Buttons">
<ItemsControl ItemsSource="{Binding ButtonItems}" HorizontalAlignment="Left">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Margin="2"
MinWidth="80"
Content="{Binding Text}"
Command="{Binding Command}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
<GroupBox Header="Edit Buttons">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox
Grid.Column="0"
Margin="2"
x:Name="ButtonEditorListBox"
ItemsSource="{Binding ButtonItems}"
HorizontalAlignment="Left"
>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="2"
Text="{Binding CommandName}"
/>
<TextBlock
Margin="2"
Text="{Binding Text, StringFormat=': "{0}"'}"
/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
<ContentControl
Grid.Column="1"
Margin="8,2,2,2"
Content="{Binding SelectedItem, ElementName=ButtonEditorListBox}"
>
<ContentControl.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock
Margin="2"
HorizontalAlignment="Stretch"
FontWeight="Bold"
Text="{Binding CommandName, StringFormat={}{0}: }"
/>
<TextBox
Margin="2"
HorizontalAlignment="Stretch"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
/>
</StackPanel>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Grid>
</GroupBox>
</StackPanel>
</Grid>
Back to your question:
Inside the style for each button is a TextBlock for displaying the "Content" of the button, (since the border inside the style covers any content of the button itself).
You're doing styles wrong. Very, very wrong. I can help you fix it if you show me the style.
As I understand what you want is to modify the "text" of the button, it occurs to me that you can do it this way.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox Text="{Binding ElementName=ButtonTest, Path=Content, UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<Button Name="ButtonTest" Grid.Row="1" Width="100" Height="40">
<Button.ContentTemplate>
<DataTemplate>
<TextBlock Foreground="Blue" Text="{Binding}"></TextBlock>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</Grid>
I write my own checkbox control. This checkbox, I put inside listbox using MVVM pattern. This user control have its own class, view model and xaml view.
Here is a class:
public class MultiSelectListBox
{
public bool IsChecked { get; set; }
public string Text { get; set; }
}
ViewModel for UserControl:
public partial class VMMultiSelectListBox : ViewModelBase
{
private bool _isChecked;
private string _text;
public VMMultiSelectListBox()
{
}
public VMMultiSelectListBox(MultiSelectListBox.BusinnesModel.MultiSelectListBox item)
{
IsChecked = item.IsChecked;
Text = item.Text;
}
public bool IsChecked
{
get { return _isChecked; }
set { _isChecked = value; NotifyPropertyChanged("IsChecked"); }
}
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged("Text"); }
}
}
And here is xaml:
<UserControl x:Class="MES.UserControls.MultiSelectListBox.UCMultiSelectListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MES.UserControls.MultiSelectListBox">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="{Binding Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</UserControl>
Now I want to bind this UserControl inside my ListBox, which is located in main form.
This is what I'm using in my form xaml.
<Expander x:Name="expanderProccesses" Header="Procesy" IsExpanded="{Binding IsExpanded}" Grid.Column="1" Grid.Row="0" VerticalAlignment="Top" Margin="5,6,-30,0">
<ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled" ItemsSource="{Binding ProccessFilter}" SelectedItem="{Binding SelectedProcess, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<ucLb:UCMultiSelectListBox/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Expander>
Last thing is view model of this form.
public VMMultiSelectListBox SelectedProcess
{
get { return _selectedProccess; }
set {
_selectedProccess = value;
NotifyPropertyChanged("SelectedProcess");
NotifyPropertyChanged("ProccessFilter");
}
}
public ObservableCollection<VMMultiSelectListBox> ProccessFilter
{
get { return _proccesFilter; }
set { _proccesFilter = value; NotifyPropertyChanged("ProccessFilter");}
}
Something I'm doing wrong. In selectedProcces it always leap in getter, but not in setter, which I need. I don't exactly know why.
I thing what you are trying to do can be achieved in a more standard context, by binding IsSelected property in ItemContainerStyle and using a CheckBox in the ItemTemplate:
<ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled" SelectionMode="Extended" ItemsSource="{Binding ProccessFilter}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsChecked, Mode=TwoWay}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Please note that you should set SelectionMode="Extended".
Hope it helps.
I have a Toolbox (Visual Studio alike) and a textbox where user can filter. The filter is working however the items in the ListBox always remain not expanded.
View.xaml
<ListBox x:Name="ListBox" Grid.Row="1" ItemsSource="{Binding Items}"
PreviewMouseLeftButtonDown="OnListBoxPreviewMouseLeftButtonDown" MouseMove="OnListBoxMouseMove"
Background="Transparent" BorderThickness="0" ScrollViewer.CanContentScroll="False">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<gem:ExpanderEx Header="{Binding Name}" IsExpanded="{Binding IsSelected, Mode=TwoWay}">
<ItemsPresenter />
</gem:ExpanderEx>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="15"
Text="{Binding Path=Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="18 0 0 0" ToolTip="{Binding Help}">
<Image Source="{Binding IconSource, Converter={StaticResource NullableValueConverter}}" Margin="0 0 5 0" Width="16" />
<TextBlock Text="{Binding Name}" Padding="2" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ViewModel.cs
items = new BindableCollection<ToolboxItemViewModel>();
collectionView = CollectionViewSource.GetDefaultView(items);
collectionView.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
collectionView.GroupDescriptions.Add(new PropertyGroupDescription("SubCategory"));
collectionView.Filter = ToolBoxFilter;
private readonly BindableCollection<ToolboxItemViewModel> items;
public IObservableCollection<ToolboxItemViewModel> Items { get { return items; } }
private string searchTerm;
public string SearchTerm
{
get { return searchTerm; }
set
{
if (searchTerm == value)
return;
searchTerm = value;
NotifyOfPropertyChange(() => SearchTerm);
//TODO: implement a defer here (Rx Extensions might help)
collectionView.Refresh(); //Refresh the filter.
}
}
ToolBoxItem.cs
public class ToolboxItemViewModel : PropertyChangedBase
{
private readonly ToolboxItem model;
public ToolboxItemViewModel(ToolboxItem model)
{
this.model = model;
IsSelected = false;
}
public ToolboxItem Model
{
get { return model; }
}
public string Name
{
get { return model.Name; }
}
public string Category
{
get { return model.Category; }
}
public string SubCategory
{
get { return model.SubCategory; }
}
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
NotifyOfPropertyChange(() => IsSelected);
}
}
How can I expand the grouped items when filtering?
Or another approach, how to expand the group item if there is any ListboxItem selected inside.
EDIT
Trying to figure it out, turns out I have a binding error on gem:ExpanderEx IsExpanded="{Binding IsSelected}"
BindingExpression path error 'IsSelected' property not found on 'object' 'CollectionViewGroupInternal'
In your collectionView filter, add yourObject.IsSelected = true;.
When you return true in your filter, you can alter the properties from your ToolboxItemViewModel object.
bool ToolBoxFilter(object item)
{
if (Search Criteria Match)
{
ToolboxItemViewModel model = (ToolboxItemViewModel)item;
model.IsSelected = true;
... rest of your code
}
}
I have a listbox with a datatemplate that contains a checkbox and textblock. How do I get the multiselection working with the checkbox in the template so that selection is based on the isChecked property of the checkbox? The need I have is to have a dropdown with checkboxes that could cater for multiselection. This is what I have sofar. Please feel free to give suggestions on where I could better this code as this is the whole point.
XAML:
<DataTemplate x:Key="WorkCentreItem">
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding WorkCentre}" IsChecked="{Binding IsChecked}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
<telerik:RadListBox
SelectionMode="Multiple"
Grid.Row="2"
Grid.ColumnSpan="2"
Grid.RowSpan="1"
Margin="-1,20,0,3"
ItemsSource="{Binding SampleWorkCentres}"
ItemTemplate="{StaticResource WorkCentreItem}"
ScrollViewer.CanContentScroll="True"
SelectionChanged="RadListBox_SelectionChanged">
</telerik:RadListBox>
Model:
#region SampleWorkCentres
public const string SampleWorkCentresPropertyName = "SampleWorkCentres";
private ObservableCollection<BomWorkCentre> _sampleWorkCentres;
public ObservableCollection<BomWorkCentre> SampleWorkCentres
{
get
{
if (this._sampleWorkCentres == null)
{
using (SysproKitIssueEntities db = new SysproKitIssueEntities())
{
this._sampleWorkCentres = new ObservableCollection<BomWorkCentre>(db.BomWorkCentres.Select(x => x).Distinct().ToList());
}
}
return this._sampleWorkCentres;
}
set
{
if (this._sampleWorkCentres == value)
{
return;
}
this._sampleWorkCentres = value;
this.RaisePropertyChanged(SampleWorkCentresPropertyName);
}
}
#endregion
#region SelectedWorkCentres
public const string SelectedWorkCentresPropertyName = "SelectedWorkCentres";
private ObservableCollection<BomWorkCentre> _selectedWorkCentres = new ObservableCollection<BomWorkCentre>();
public ObservableCollection<BomWorkCentre> SelectedWorkCentres
{
get
{
return this._selectedWorkCentres;
}
set
{
if (this._selectedWorkCentres != value)
{
this._selectedWorkCentres = value;
}
this._sampleGridItems = null;
this.RaisePropertyChanged(SampleGridItemsPropertyName);
this.RaisePropertyChanged(SelectedWorkCentresPropertyName);
}
}
#endregion
You should data bind the Checkbox.IsChecked to the ListBoxItem.IsSelected Property using a RelativeSource Binding:
<CheckBox Content="{Binding WorkCentre}" IsChecked="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
I cannot understand what I'm doing wrong. I want to group items in listView.
In result I want to see something like that:
It'm using MVVM pattern. It's my XAML code.
<CollectionViewSource x:Key="EmploeeGroup"
Source="{Binding Path=AllEmploees}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="FirstName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<ListView AlternationCount="2"
DataContext="{StaticResource EmploeeGroup}"
ItemsSource="{Binding IsAsync=True}" Padding="0,0,0,10">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" BorderBrush="#FFA4B97F"
BorderThickness="0,0,0,1">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold"
Text="Name: "/>
<TextBlock FontWeight="Bold"
Text="{Binding Path=FirstName}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn Width="150"
Header="FirstName"
DisplayMemberBinding="{Binding Path=FirstName}"/>
<GridViewColumn Width="150"
Header="LastName"
DisplayMemberBinding="{Binding Path=LastName}"/>
</GridView>
</ListView.View>
</ListView>
It's my EmploeeListViewModel.cs
public class EmploeeListViewModel: ViewModelBase
{
readonly EmploeeRepository _emploeeRepository;
private ObservableCollection<EmploeeViewModel> _allmpl;
public ObservableCollection<EmploeeViewModel> AllEmploees
{
get
{
if (_allmpl == null)
{
_allmpl = new ObservableCollection<EmploeeViewModel>();
CreateAllEmploee();
}
return _allmpl;
}
}
public EmploeeListViewModel(EmploeeRepository emploeeRepository)
{
if (emploeeRepository == null)
throw new ArgumentNullException("emploeeRepository");
_emploeeRepository = emploeeRepository;
_emploeeRepository.EmploeeAdded += this.OnEmploeeAddedToRepository;
}
private void CreateAllEmploee()
{
List<EmploeeViewModel> all =
(from emploee in _emploeeRepository.GetEmploees()
select new EmploeeViewModel(emploee)).ToList();
foreach (EmploeeViewModel evm in all)
{
evm.PropertyChanged += this.OnEmploeeViewModelPropertyChanged;
AllEmploees.Add(evm);
}
this.AllEmploees.CollectionChanged += this.OnCollectionChanged;
}
//this.OnCollectionChanged;
//this.OnEmploeeViewModelPropertyChanged;
}
EmploeeViewModel.cs
public class EmploeeViewModel : ViewModelBase
{
#region Fields
Emploee _emploee;
bool _isSelected;
#endregion
#region Constructor
public EmploeeViewModel(Emploee emploee)
{
if (emploee == null)
throw new ArgumentNullException("emploee");
this._emploee = emploee;
}
#endregion
#region Emploee Properties
public bool IsSelected
{
get { return _isSelected; }
set
{
if (value == _isSelected)
return;
_isSelected = value;
base.OnPropertyChanged("IsSelected");
}
}
public string FirstName
{
get { return _emploee.FirstName; }
set
{
if (value == _emploee.FirstName)
return;
_emploee.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
public string LastName
{
get { return _emploee.LastName; }
set
{
if (value == _emploee.LastName)
return;
_emploee.LastName = value;
base.OnPropertyChanged("LastName");
}
}
#endregion
}
Why can not I bind "FirstName"
property with Expander.Header
TextBlock?
Why have I object type
MS.Internal.Data.CollectionViewGroupInternal
inside Expander.Header(if i wrote inside
Expander.Header
Text="{Binding}")>?
How should I
change my XAML or .CS code to produce
these results?
I found answer on this question by myself.
The object that is sent into the converter is of the type: MS.Internal.Data.CollectionViewGroupInternal.
The main reason is to use "Name" for databinding the group names is simply because that is the property in CollectionViewGroupInternal that contains the name that the current "group collection" has (according to the GroupDescription that you specified).
Not important What was GropertyName in PropertyGroupDescription.
You have to always use {Binding Path=Name} in GroupStyle container.
I had to change only one string in my XAML.
From:
<TextBlock FontWeight="Bold" Text="{Binding Path=FirstName}"/>
To:
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/>
Just came across the same Problem regarding the "Name / FirstName" Binding-Problem and found a solution for my project here:
Grouping ListView WPF
In short, withing the Expander-Tag you can set the DataContext to "{Binding Items}". After that you can use your original property names.