I am trying to have a datagrid display a sorted collection the first time it is loaded. The datagrid loads fine if I do not try to sort it but as soon as I put in a CollectionViewSource in, nothing loads to the datagrid. What am I missing in the below code that will load the collection and have it sorted?
Here is the XAML
<Window.Resources>
<CollectionViewSource Source="{Binding TdStatusCol}" x:Key="StatusItems">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="RegionNm" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
.....
<DataGrid x:Name="dgThreads" ItemsSource="{Binding Source={StaticResource StatusItems}}" AutoGenerateColumns="False" Margin="10,5,10,5"
RenderTransformOrigin="0.487,-0.31" AlternatingRowBackground="#FFB5CFA7"
CanUserAddRows="False" CanUserDeleteRows="False" Grid.Row="1" Grid.Column="0" Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
<DataGrid.Columns>
<DataGridTextColumn x:Name="colRegionNm" Header = "Region Name" Binding="{Binding RegionNm}"/>
<DataGridTextColumn x:Name="colStatus" Header = "Status" Binding="{Binding Status}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding StatusChange}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="colThdState" Header = "Thread State" Binding="{Binding ThdState}" Visibility="Hidden">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding ThdStateChange}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="colAction" Header = "Action" Binding="{Binding Action}" Visibility="Hidden">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding ActionChange}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="colFilesProcessed" Header = "Files Processed" Binding="{Binding FilesProcessed}"/>
<DataGridTextColumn x:Name="colNumErrors" Header = "Number of Errors" Binding="{Binding NumErrors}"/>
<DataGridTextColumn x:Name="colLastUpdated" Header = "Last Updated" Binding="{Binding LastUpdated}"/>
</DataGrid.Columns>
</DataGrid>
Here is the CS code:
public partial class MainWindow : Window
{
public ObservableCollection<TStatus> TdStatusCol { get; set; }
public MainWindow()
{
TdStatusCol = new ObservableCollection<TStatus>();
TdStatusCol.Add(new TStatus()
{
RegionNm = "Second",
Status = "------",
ThdState = "------",
Action = "------",
FilesProcessed = "------",
NumErrors = "------",
LastUpdated = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
});
TdStatusCol.Add(new TStatus()
{
RegionNm = "Third",
Status = "------",
ThdState = "------",
Action = "------",
FilesProcessed = "------",
NumErrors = "------",
LastUpdated = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
});
TdStatusCol.Add(new TStatus()
{
RegionNm = "First",
Status = "------",
ThdState = "------",
Action = "------",
FilesProcessed = "------",
NumErrors = "------",
LastUpdated = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
});
}
}
public class TStatus : INotifyPropertyChanged
{
private string
_status,
_action,
_thdstate,
_filesprocessed,
_numerrors,
_lastupdated;
public string RegionNm { get; set; }
public string Status
{
get { return _status; }
set
{
if(_status != value)
{
_status = value;
RaisePropertyChanged("Status");
RaisePropertyChanged("StatusChange");
}
}
}
public Brush StatusChange
{
get
{
switch(_status)
{
case "Running":
return Brushes.LightGreen;
case "Closed":
return Brushes.LightPink;
case "Errored":
return Brushes.Red;
default:
return Brushes.LightYellow;
}
}
}
public string Action
{
get { return _action; }
set
{
_action = value;
RaisePropertyChanged("Action");
}
}
public Brush ActionChange
{
get
{
switch (_action)
{
case "Run":
return Brushes.LightGreen;
case "Stop":
return Brushes.LightPink;
default:
return Brushes.LightYellow;
}
}
}
public string ThdState
{
get { return _thdstate; }
set
{
_thdstate = value;
RaisePropertyChanged("ThdState");
}
}
public Brush ThdStateChange
{
get
{
switch (_thdstate)
{
case "Running":
return Brushes.LightGreen;
case "Closed":
return Brushes.LightPink;
case "Errored":
return Brushes.Red;
default:
return Brushes.LightYellow;
}
}
}
public string FilesProcessed
{
get { return _filesprocessed; }
set
{
_filesprocessed = value;
RaisePropertyChanged("FilesProcessed");
}
}
public string NumErrors
{
get { return _numerrors; }
set
{
_numerrors = value;
RaisePropertyChanged("NumErrors");
}
}
public string LastUpdated
{
get {return _lastupdated;}
set
{
_lastupdated = value;
RaisePropertyChanged("LastUpdated");
}
}
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler == null) return;
handler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Update: I have followed another post and removed the CollectionViewSource in the XAML. Set the DataGrid ItemSource = "{Binding TdStatusCol}" and added the following code to CS code
public ICollectionView StatusView { get; set; }
In Public MainWindow() added:
StatusView = CollectionViewSource.GetDefaultView(TdStatusCol);
StatusView.SortDescriptions.Add(new SortDescription("RegionNm", ListSortDirection.Ascending));
Why does second option work over the first and which one is better code logic? Thanks