The project is huge, with thousands of files and probably a million lines of code. But I hope I have successfully extracted the relevant portion of code here.
All the important points in the source code are marked with "!!!". After the constructor of AssetSelectorPM is called, its "SelectedAssets" property is filled in the other code.
Anyway, what do you suggest to select rows at the startup? As "SelectedItems" cannot be bound in XAML, but must be in the C# code. Should this work already if bound in the code?
Thanks,
Sergej
==============================
AssetDto.cs:
==============================
[Serializable]
public class AssetDto: GroupedDtoBase {
private Guid _id;
public Guid ID {
get {return _id;}
set {_id = value; RaisePropertyChanged(() => ID);}
}
private int _assetID;
public int AssetID {
get {return _assetID;}
set {_assetID = value; RaisePropertyChanged(() => AssetID);}
}
private string _registrationNumber;
public string RegistrationNumber {
get {return _registrationNumber;}
set {_registrationNumber = value; RaisePropertyChanged(() => RegistrationNumber);}
}
// other properties here...
}
==============================
IAssetSelectorPM.cs:
==============================
public interface IAssetsSelectorPM {
GenericViewCollection<AssetDto> Assets {get;}
GenericViewCollection<AssetDto> SelectedAssets {get; set;}
IAssetsSelectorView View {get;}
}
==============================
IAssetSelectorView.cs:
==============================
public interface IAssetsSelectorView {
IAssetsSelectorPM Model {set;}
}
==============================
AssetSelectorView.xaml:
==============================
<UserControl.Resources>
<xcdg:DataGridCollectionViewSource x:Key="Assets"
Source="{Binding Assets}"
AutoFilterMode="None" AutoCreateItemProperties="true" >
</xcdg:DataGridCollectionViewSource>
</UserControl.Resources>
<DockPanel>
<xcdg:DataGridControl Name="UI_AssetsGrid" Grid.Row="0" AutoCreateColumns="True"
ItemScrollingBehavior="Immediate" ReadOnly="True"
ItemsSource="{Binding Source={StaticResource Assets}}"
SelectionMode="Extended" NavigationBehavior="RowOnly"
Margin="5,5,0,2">
</xcdg:DataGridControl>
</DockPanel>
==============================
AssetSelectorView.xaml.cs:
==============================
public partial class AssetsSelectorView: UserControl, IAssetsSelectorView {
public AssetsSelectorView() {
InitializeComponent();
}
public IAssetsSelectorPM Model {
set {
DataContext = value;
// !!! set bindings that can not be set in xaml
new CollectionBinder(UI_AssetsGrid.SelectedItems, Model.SelectedAssets, BindingMode.TwoWay);
}
get {
return DataContext as IAssetsSelectorPM;
}
}
}
==============================
AssetSelectorPM.cs:
==============================
public class AssetsSelectorPM: BasePM, IAssetsSelectorPM {
private readonly IAssetService _assetService;
private readonly IGroupDefinitionsStorage _groupDefinitionsStorage;
public IAssetsSelectorView View {get; private set;}
public AssetsSelectorPM(IAssetsSelectorView view, IAssetService assetService, IGroupDefinitionsStorage groupDefinitionsStorage, IUIFacade uiFacade, IAssetFilterPM assetFilterPM) {
_assetService = assetService;
_groupDefinitionsStorage = groupDefinitionsStorage;
_uiFacade = uiFacade;
FilterPM = assetFilterPM;
FilterPM.UpdateResultsCommand = new DelegateCommand<object>(x => PopulateAssets());
PopulateAssets();
View = view;
View.Model = this;
// !!! here, the "Assets" is already filled, but the "Items" in Datagrid is not bound, so I cannot manually select the Items here.
}
private GenericViewCollection<AssetDto> _assets;
private GenericViewCollection<AssetDto> _selectedAssets = new GenericViewCollection<AssetDto>();
private readonly IUIFacade _uiFacade;
public GenericViewCollection<AssetDto> Assets {
get {return _assets;}
private set {
_assets = value;
RaisePropertyChanged(() => Assets);
}
}
public GenericViewCollection<AssetDto> SelectedAssets {
get {return _selectedAssets;}
set {_selectedAssets = value;}
}
private void PopulateAssets() {
var pds = new List<PropertyDescriptor> {
new NamedPropertyDescriptor<AssetDto>(x => x.InternalNumber, Resources.InternalNumber),
new NamedPropertyDescriptor<AssetDto>(x => x.RegistrationNumber, Resources.LicensePlate)
};
try {
GroupDefinitionsDescriptorProvider<Asset>.AppendPropertyDescriptorsForGroupDefinitions(
_groupDefinitionsStorage.GroupDefinitionsForName(Asset.AssetGroupingName), pds);
var assets = _assetService.GetAssetDtosForLoggedUser(FilterPM.Filter);
Assets = new GenericViewCollection<AssetDto>(assets, pds);
}
catch (Exception ee) {
_uiFacade.ShowErrorMessage(ee.Message, ee);
}
}
}
==============================
CollectionBinder.cs:
==============================
public class CollectionBinder {
private IList _sourceCollection;
private IList _targetCollection;
private Func<object, object> _sourceToTargetConversion;
private Func<object, object> _targetToSourceConversion;
private bool _skipNullValues;
public CollectionBinder(IList sourceCollection, IList targetCollection, BindingMode bindingMode) {
ArgumentHelper.AssertNotNull(sourceCollection, "sourceCollection");
ArgumentHelper.AssertNotNull(targetCollection, "targetCollection");
ArgumentHelper.AssertEnumMember<BindingMode>(bindingMode, "bindingMode", BindingMode.OneTime, BindingMode.OneWay, BindingMode.OneWayToSource, BindingMode.TwoWay);
_sourceToTargetConversion = x => x;
_targetToSourceConversion = x => x;
_skipNullValues = false;
if (bindingMode == BindingMode.OneWayToSource) {
_targetCollection = sourceCollection;
_sourceCollection = targetCollection;
bindingMode = BindingMode.OneWay;
}
else {
_sourceCollection = sourceCollection;
_targetCollection = targetCollection;
}
InitialSync(sourceCollection, targetCollection);
var notifiableSource = _sourceCollection as INotifyCollectionChanged;
var notifiableTarget = _targetCollection as INotifyCollectionChanged;
if ((bindingMode == BindingMode.OneWay || bindingMode == BindingMode.TwoWay) && notifiableSource != null) {
notifiableSource.CollectionChanged += CollectionBinder_SourceCollectionChanged;
}
if (bindingMode == BindingMode.TwoWay && notifiableTarget != null)
notifiableTarget.CollectionChanged += CollectionBinder_TargetCollectionChanged;
}
public CollectionBinder(IList sourceCollection, IList targetCollection, BindingMode bindingMode, Func<object, object> sourceToTargetConversion, Func<object, object> targetToSourceConversion)
: this(sourceCollection, targetCollection, bindingMode) {
_sourceToTargetConversion = sourceToTargetConversion;
_targetToSourceConversion = targetToSourceConversion;
}
public CollectionBinder(IList sourceCollection, IList targetCollection, BindingMode bindingMode, Func<object, object> sourceToTargetConversion, Func<object, object> targetToSourceConversion, bool skipNullValues)
: this(sourceCollection, targetCollection, bindingMode) {
_sourceToTargetConversion = sourceToTargetConversion;
_targetToSourceConversion = targetToSourceConversion;
_skipNullValues = true;
}
public CollectionBinder(IList sourceCollection, IList targetCollection, BindingMode bindingMode, Func<object, object> sourceToTargetConversion)
: this(sourceCollection, targetCollection, bindingMode) {
_sourceToTargetConversion = sourceToTargetConversion;
}
private void InitialSync(IList sourceCollection, IList targetCollection) {
targetCollection.Clear();
foreach (object item in sourceCollection) {
var converted = _sourceToTargetConversion(item);
if (converted == null && _skipNullValues) continue;
targetCollection.Add(_sourceToTargetConversion(item));
}
}
private bool _sourceChangedFirst = false;
private void CollectionBinder_SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if (_targetChangedFirst) return;
_sourceChangedFirst = true;
SynchroniseCollection(_targetCollection, e, _sourceToTargetConversion);
_sourceChangedFirst = false;
}
private bool _targetChangedFirst = false;
private void CollectionBinder_TargetCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if (_sourceChangedFirst) return;
_targetChangedFirst = true;
SynchroniseCollection(_sourceCollection, e, _targetToSourceConversion);
_targetChangedFirst = false;
}
private void SynchroniseCollection(IList collectionToSync, NotifyCollectionChangedEventArgs e, Func<object, object> converter) {
if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace) {
foreach (object item in e.NewItems) {
var converted = converter(item);
if (converted == null && _skipNullValues) continue;
collectionToSync.Add(converted);
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) {
foreach (object item in e.OldItems) {
var converted = converter(item);
if (converted == null && _skipNullValues)
continue;
collectionToSync.Remove(converted);
}
}
else if (e.Action == NotifyCollectionChangedAction.Reset) {
if (collectionToSync == _targetCollection)
InitialSync(_sourceCollection, _targetCollection);
else
InitialSync(_targetCollection, _sourceCollection);
}
}
}