diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs
index 60739c2b5..7b7a45919 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs
@@ -96,8 +96,8 @@ namespace Artemis.Core
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{newPath}'");
ListPath = newPath;
- ListType = listType;
- IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
+ ListType = listType.GetGenericArguments()[0];
+ IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
}
else
{
@@ -182,10 +182,13 @@ namespace Artemis.Core
// Ensure the list path is valid and points to a list
DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
- if (!listPath.IsValid || !typeof(IList).IsAssignableFrom(listPath.GetPropertyType()))
+ Type listType = listPath.GetPropertyType()!;
+ if (!listPath.IsValid || !typeof(IList).IsAssignableFrom(listType))
return;
ListPath = listPath;
+ ListType = listType.GetGenericArguments()[0];
+ IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
// There should only be one child and it should be a group
if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup)
diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs
index f7e484254..628ccfe9e 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs
@@ -70,18 +70,17 @@ namespace Artemis.Core
/// Updates the left side of the predicate
///
/// The path pointing to the left side value inside the list
- public void UpdateLeftSide(string path)
+ public void UpdateLeftSide(string? path)
{
if (DataModelConditionList.IsPrimitiveList)
throw new ArtemisCoreException("Cannot apply a left side to a predicate inside a primitive list");
- if (!ListContainsInnerPath(path))
- throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
LeftPath?.Dispose();
- LeftPath = DataModelConditionList.ListType != null
- ? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path)
- : null;
-
+ if (path != null && DataModelConditionList.ListType != null)
+ LeftPath = new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path);
+ else
+ LeftPath = null;
+
ValidateOperator();
ValidateRightSide();
}
@@ -91,16 +90,15 @@ namespace Artemis.Core
/// and re-compiles the expression
///
/// The path pointing to the right side value inside the list
- public void UpdateRightSideDynamic(string path)
+ public void UpdateRightSideDynamic(string? path)
{
- if (!ListContainsInnerPath(path))
- throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
+ RightPath?.Dispose();
+ if (path != null && DataModelConditionList.ListType != null)
+ RightPath = new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path);
+ else
+ RightPath = null;
PredicateType = ListRightSideType.DynamicList;
- RightPath?.Dispose();
- RightPath = DataModelConditionList.ListType != null
- ? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path)
- : null;
}
///
@@ -109,20 +107,27 @@ namespace Artemis.Core
///
///
/// The path pointing to the right side value inside the list
- public void UpdateRightSideDynamic(DataModel dataModel, string path)
+ public void UpdateRightSideDynamic(DataModel? dataModel, string? path)
{
if (dataModel != null && path == null)
throw new ArtemisCoreException("If a data model is provided, a path is also required");
if (dataModel == null && path != null)
throw new ArtemisCoreException("If path is provided, a data model is also required");
+ RightPath?.Dispose();
if (dataModel != null)
- if (!dataModel.ContainsPath(path))
- throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
+ {
+ DataModelPath newPath = new DataModelPath(dataModel, path);
+ if (!newPath.IsValid)
+ throw new ArtemisCoreException($"New right path '{newPath}' is invalid");
+ RightPath = newPath;
+ }
+ else
+ {
+ RightPath = null;
+ }
PredicateType = ListRightSideType.Dynamic;
- RightPath?.Dispose();
- RightPath = new DataModelPath(dataModel, path);
}
///
diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs
index 601bea3ff..12e7a5b6f 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs
@@ -76,7 +76,7 @@ namespace Artemis.Core
throw new ArtemisCoreException("If path is provided, a data model is also required");
LeftPath?.Dispose();
- if (dataModel != null && path != null)
+ if (dataModel != null)
{
DataModelPath newPath = new DataModelPath(dataModel, path);
if (!newPath.IsValid)
@@ -105,7 +105,7 @@ namespace Artemis.Core
throw new ArtemisCoreException("If path is provided, a data model is also required");
RightPath?.Dispose();
- if (dataModel != null && path != null)
+ if (dataModel != null)
{
DataModelPath newPath = new DataModelPath(dataModel, path);
if (!newPath.IsValid)
diff --git a/src/Artemis.Core/Models/Profile/Conditions/ListPredicateWrapperDataModel.cs b/src/Artemis.Core/Models/Profile/Conditions/ListPredicateWrapperDataModel.cs
index e134b5dc8..884dd77c0 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/ListPredicateWrapperDataModel.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/ListPredicateWrapperDataModel.cs
@@ -10,6 +10,12 @@ namespace Artemis.Core
public abstract class ListPredicateWrapperDataModel : DataModel
{
+ internal ListPredicateWrapperDataModel()
+ {
+ PluginInfo = Constants.CorePluginInfo;
+ }
+
+ [DataModelIgnore]
public object? UntypedValue { get; set; }
public static ListPredicateWrapperDataModel Create(Type type)
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs
index 6d6afaa64..0eca0e386 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared.Services;
@@ -10,11 +11,12 @@ namespace Artemis.UI.Shared
private int _index;
private Type _listType;
- public DataModelListPropertiesViewModel(object listItem) : base(null, null, null)
+ public DataModelListPropertiesViewModel(Type listType) : base(null, null, null)
{
- DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType());
- ListType = listItem.GetType();
- DisplayValue = listItem;
+ DataModel = ListPredicateWrapperDataModel.Create(listType);
+ ListType = listType;
+
+ IsRootViewModel = false;
}
public int Index
@@ -35,18 +37,21 @@ namespace Artemis.UI.Shared
set => SetAndNotify(ref _displayValue, value);
}
+ public DataModelVisualizationViewModel DisplayViewModel => Children.FirstOrDefault();
+
public override string DisplayPath => null;
public override void Update(IDataModelUIService dataModelUIService)
{
- // Display value gets updated by parent, don't do anything if it is null
- if (DisplayValue == null)
+ ((ListPredicateWrapperDataModel) DataModel).UntypedValue = DisplayValue;
+
+ PopulateProperties(dataModelUIService);
+ if (DisplayViewModel == null)
return;
- ListType = DisplayValue.GetType();
- PopulateProperties(dataModelUIService);
- foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
- dataModelVisualizationViewModel.Update(dataModelUIService);
+ if (IsVisualizationExpanded && !DisplayViewModel.IsVisualizationExpanded)
+ DisplayViewModel.IsVisualizationExpanded = IsVisualizationExpanded;
+ DisplayViewModel.Update(dataModelUIService);
}
public override object GetCurrentValue()
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs
index db47e9f7a..42767fd67 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs
@@ -9,19 +9,17 @@ namespace Artemis.UI.Shared
private int _index;
private Type _listType;
- public DataModelListPropertyViewModel(object listItem, DataModelDisplayViewModel displayViewModel) : base(null, null, null)
+ public DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel) : base(null, null, null)
{
- DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType());
- ListType = listItem.GetType();
- DisplayValue = listItem;
+ DataModel = ListPredicateWrapperDataModel.Create(listType);
+ ListType = listType;
DisplayViewModel = displayViewModel;
}
- public DataModelListPropertyViewModel(object listItem) : base(null, null, null)
+ public DataModelListPropertyViewModel(Type listType) : base(null, null, null)
{
- DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType());
- ListType = listItem.GetType();
- DisplayValue = listItem;
+ DataModel = ListPredicateWrapperDataModel.Create(listType);
+ ListType = listType;
}
public int Index
@@ -47,6 +45,8 @@ namespace Artemis.UI.Shared
if (DisplayValue == null)
return;
+ ((ListPredicateWrapperDataModel)DataModel).UntypedValue = DisplayValue;
+
if (DisplayViewModel == null)
DisplayViewModel = dataModelUIService.GetDataModelDisplayViewModel(DisplayValue.GetType(), true);
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
index 28c483320..c4c337e96 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
@@ -33,19 +33,19 @@ namespace Artemis.UI.Shared
public DataModelPropertiesViewModel GetListTypeViewModel(IDataModelUIService dataModelUIService)
{
- Type type = DataModelPath.GetPropertyType();
- if (type == null)
+ Type listType = DataModelPath.GetPropertyType()?.GenericTypeArguments[0];
+ if (listType == null)
return null;
// Create a property VM describing the type of the list
- DataModelVisualizationViewModel viewModel = CreateListChild(dataModelUIService, type.GenericTypeArguments[0]);
+ DataModelVisualizationViewModel viewModel = CreateListChild(dataModelUIService, listType);
+ viewModel.Update(dataModelUIService);
// Put an empty value into the list type property view model
if (viewModel is DataModelListPropertiesViewModel dataModelListClassViewModel)
{
return dataModelListClassViewModel;
}
-
if (viewModel is DataModelListPropertyViewModel dataModelListPropertyViewModel)
{
dataModelListPropertyViewModel.DisplayValue = Activator.CreateInstance(dataModelListPropertyViewModel.ListType);
@@ -67,12 +67,15 @@ namespace Artemis.UI.Shared
return;
int index = 0;
- foreach (object? item in List)
+ foreach (object item in List)
{
+ if (item == null)
+ continue;
+
DataModelVisualizationViewModel child;
if (ListChildren.Count <= index)
{
- child = CreateListChild(dataModelUIService, item);
+ child = CreateListChild(dataModelUIService, item.GetType());
ListChildren.Add(child);
}
else
@@ -99,20 +102,18 @@ namespace Artemis.UI.Shared
Count = $"{ListChildren.Count} {(ListChildren.Count == 1 ? "item" : "items")}";
}
- protected DataModelVisualizationViewModel CreateListChild(IDataModelUIService dataModelUIService, object listItem)
+ protected DataModelVisualizationViewModel CreateListChild(IDataModelUIService dataModelUIService, Type listType)
{
- Type listType = listItem.GetType();
-
// If a display VM was found, prefer to use that in any case
DataModelDisplayViewModel typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType);
if (typeViewModel != null)
- return new DataModelListPropertyViewModel(listItem, typeViewModel);
+ return new DataModelListPropertyViewModel(listType, typeViewModel);
// For primitives, create a property view model, it may be null that is fine
if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string))
- return new DataModelListPropertyViewModel(listItem);
+ return new DataModelListPropertyViewModel(listType);
// For other value types create a child view model
if (listType.IsClass || listType.IsStruct())
- return new DataModelListPropertiesViewModel(listItem);
+ return new DataModelListPropertiesViewModel(listType);
return null;
}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
index 67651698f..69faf8fe0 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
@@ -35,7 +35,7 @@ namespace Artemis.UI.Shared
PropertyDescription = DataModelPath?.GetPropertyDescription() ?? DataModel.DataModelDescription;
}
- public bool IsRootViewModel { get; }
+ public bool IsRootViewModel { get; protected set; }
public DataModelPath DataModelPath { get; }
public string Path => DataModelPath?.Path;
@@ -81,7 +81,7 @@ namespace Artemis.UI.Shared
}
}
- public virtual string DisplayPath => Path?.Replace(".", " › ");
+ public virtual string DisplayPath => string.Join(" › ", DataModelPath.Segments.Select(s => s.GetPropertyDescription()?.Name ?? s.Identifier));
///
/// Updates the datamodel and if in an parent, any children
@@ -146,7 +146,7 @@ namespace Artemis.UI.Shared
return null;
if (propertyPath == null)
return null;
- if (Path.StartsWith(propertyPath, StringComparison.OrdinalIgnoreCase))
+ if (Path != null && Path.StartsWith(propertyPath, StringComparison.OrdinalIgnoreCase))
return null;
}
@@ -183,7 +183,7 @@ namespace Artemis.UI.Shared
if (IsRootViewModel)
return;
- Type modelType = Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType();
+ Type modelType = Parent == null || Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType();
// Add missing static children
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
@@ -210,7 +210,7 @@ namespace Artemis.UI.Shared
}
// Add missing dynamic children
- object value = Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
+ object value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
if (value is DataModel dataModel)
{
foreach (KeyValuePair kvp in dataModel.DynamicDataModels)
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionListPredicateViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionListPredicateViewModel.cs
index fe0c16bb0..b1286e616 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionListPredicateViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionListPredicateViewModel.cs
@@ -117,10 +117,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
if (!_isPrimitiveList)
{
- LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
+ // Lists use a different color
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
- LeftSideSelectionViewModel.SelectedPropertyViewModel = LeftSideSelectionViewModel.DataModelViewModel.GetChildByPath(
- listDataModelGuid.Value, DataModelConditionListPredicate.DataModelConditionList.ListPath.Path
+ LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
+ LeftSideSelectionViewModel.PopulateSelectedPropertyViewModel(
+ DataModelConditionListPredicate.LeftPath?.Target,
+ DataModelConditionListPredicate.LeftPath?.Path
);
}
@@ -141,9 +143,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
}
// Ensure the right side has the proper VM
- if ((DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic ||
- DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicList) &&
- SelectedOperator.SupportsRightSide)
+ ListRightSideType type = DataModelConditionListPredicate.PredicateType;
+ if ((type == ListRightSideType.Dynamic || type == ListRightSideType.DynamicList) && SelectedOperator.SupportsRightSide)
{
DisposeRightSideStatic();
if (RightSideSelectionViewModel == null)
@@ -157,15 +158,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
}
RightSideSelectionViewModel.FilterTypes = new[] {leftSideType};
- if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic)
- RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
- DataModelConditionListPredicate.RightPath?.Target,
- DataModelConditionListPredicate.RightPath?.Path
- );
- else
- RightSideSelectionViewModel.SelectedPropertyViewModel = RightSideSelectionViewModel.DataModelViewModel.GetChildByPath(
- listDataModelGuid.Value, DataModelConditionListPredicate.RightPath?.Path
- );
+ RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
+ DataModelConditionListPredicate.RightPath?.Target,
+ DataModelConditionListPredicate.RightPath?.Path
+ );
}
else if (SelectedOperator.SupportsRightSide)
{
diff --git a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml
index c15419957..f7051ca0f 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml
@@ -117,7 +117,7 @@
-
+
List item []