Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xamarin/Xamarin.PropertyEditing.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Maupin <me@ermau.com>2018-09-18 18:01:24 +0300
committerGitHub <noreply@github.com>2018-09-18 18:01:24 +0300
commit3a99673a4082de39bedc5018857d5f52fea66e1a (patch)
tree5f0005e59c60346ceb093811ce4e984a9cd08bed
parentcdf1ae946a46435a78ae8dc6d0a668c48aca436f (diff)
parent06c76b699655fd789a9c2c9ef3610d028b07cda9 (diff)
Merge pull request #406 from xamarin/ermau-fix-403
[Win] Support unconstrained values in editor with predefined values
-rw-r--r--Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs4
-rw-r--r--Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs2
-rw-r--r--Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockEnumPropertyInfo.cs5
-rw-r--r--Xamarin.PropertyEditing.Tests/PredefinedValuesViewModelTests.cs65
-rw-r--r--Xamarin.PropertyEditing.Windows/ComboBoxEx.cs60
-rw-r--r--Xamarin.PropertyEditing.Windows/Themes/Resources.xaml5
-rw-r--r--Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj1
-rw-r--r--Xamarin.PropertyEditing/ViewModels/PredefinedValuesViewModel.cs11
8 files changed, 127 insertions, 26 deletions
diff --git a/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs b/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs
index b7685ba..8004461 100644
--- a/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs
+++ b/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs
@@ -14,14 +14,14 @@ namespace Xamarin.PropertyEditing.Tests.MockControls
public void AddProperty<T> (string name, string category = null,
bool canWrite = true, bool flag = false,
IEnumerable<Type> converterTypes = null,
- string description = null, ValueSources valueSources = ValueSources.Local | ValueSources.Default | ValueSources.Binding)
+ string description = null, bool constrained = true, ValueSources valueSources = ValueSources.Local | ValueSources.Default | ValueSources.Binding)
{
IPropertyInfo propertyInfo;
if (typeof(T).IsEnum) {
var underlyingType = typeof (T).GetEnumUnderlyingType ();
var enumPropertyInfoType = typeof (MockEnumPropertyInfo<,>)
.MakeGenericType (underlyingType, typeof (T));
- propertyInfo = (IPropertyInfo)Activator.CreateInstance (enumPropertyInfoType, name, description, category, canWrite, flag, converterTypes);
+ propertyInfo = (IPropertyInfo)Activator.CreateInstance (enumPropertyInfoType, name, description, category, canWrite, flag, converterTypes, constrained);
} else {
propertyInfo = new MockPropertyInfo<T> (name, description, category, canWrite, converterTypes, valueSources);
}
diff --git a/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs b/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs
index faafc83..3fe6e51 100644
--- a/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs
+++ b/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs
@@ -16,7 +16,7 @@ namespace Xamarin.PropertyEditing.Tests.MockControls
AddProperty<int> ("UnsetInteger", ReadWrite, valueSources: ValueSources.Local);
AddProperty<float> ("FloatingPoint", ReadWrite);
AddProperty<string> ("String", ReadWrite, valueSources: ValueSources.Local | ValueSources.Resource | ValueSources.Binding);
- AddProperty<Enumeration> ("Enumeration", ReadWrite);
+ AddProperty<Enumeration> ("Enumeration", ReadWrite, constrained: false);
AddProperty<FlagsNoValues> ("FlagsNoValues", ReadWrite, canWrite: true, flag: true);
AddProperty<FlagsWithValues> ("FlagsWithValues", ReadWrite, canWrite: true, flag: true);
AddProperty<CommonPoint> ("Point", ReadWrite);
diff --git a/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockEnumPropertyInfo.cs b/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockEnumPropertyInfo.cs
index 42342f9..fd4be86 100644
--- a/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockEnumPropertyInfo.cs
+++ b/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockEnumPropertyInfo.cs
@@ -15,7 +15,7 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
where TUnderlying : struct
where TEnum : struct
{
- public MockEnumPropertyInfo (string name, string description = null, string category = "", bool canWrite = true, bool flag = false, IEnumerable<Type> converterTypes = null)
+ public MockEnumPropertyInfo (string name, string description = null, string category = "", bool canWrite = true, bool flag = false, IEnumerable<Type> converterTypes = null, bool constrained = true)
: base (name, description, category, canWrite, converterTypes)
{
var names = Enum.GetNames (typeof (TEnum));
@@ -33,12 +33,13 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
PredefinedValues = predefinedValues;
}
+ IsConstrainedToPredefined = constrained;
IsValueCombinable = flag;
}
public override Type Type => typeof (TEnum);
- public bool IsConstrainedToPredefined => true;
+ public bool IsConstrainedToPredefined { get; }
public bool IsValueCombinable { get; }
diff --git a/Xamarin.PropertyEditing.Tests/PredefinedValuesViewModelTests.cs b/Xamarin.PropertyEditing.Tests/PredefinedValuesViewModelTests.cs
index bb33343..f62b7d6 100644
--- a/Xamarin.PropertyEditing.Tests/PredefinedValuesViewModelTests.cs
+++ b/Xamarin.PropertyEditing.Tests/PredefinedValuesViewModelTests.cs
@@ -270,14 +270,38 @@ namespace Xamarin.PropertyEditing.Tests
[TestFixture]
internal class UnconstrainedPredefinedViewModelTests
- : PredefinedValuesViewModelTests<string>
+ : PredefinedValuesViewModelTests<int>
{
[Test]
+ public async Task ValueNameRepresentsValueDescriptor ()
+ {
+ var value = GetNonDefaultRandomTestValue ();
+
+ var property = GetPropertyMock ();
+ var predefined = property.As<IHavePredefinedValues<int>> ();
+ predefined.SetupGet (p => p.PredefinedValues).Returns (new Dictionary<string, int> {
+ { "Value", 0 },
+ });
+ predefined.SetupGet (p => p.IsConstrainedToPredefined).Returns (false);
+
+ var outOfBounds = "random";
+
+ var editor = GetBasicEditor (property.Object);
+ await editor.SetValueAsync (property.Object, new ValueInfo<int> {
+ Source = ValueSource.Local,
+ ValueDescriptor = outOfBounds
+ });
+
+ var vm = GetViewModel (property.Object, new[] { editor });
+ Assert.That (vm.ValueName, Is.EqualTo (outOfBounds));
+ }
+
+ [Test]
public void ValueDescriptorForUnconstrained ()
{
var property = GetPropertyMock ();
- var predefined = property.As<IHavePredefinedValues<string>> ();
- predefined.SetupGet (p => p.PredefinedValues).Returns (new Dictionary<string, string> {
+ var predefined = property.As<IHavePredefinedValues<int>> ();
+ predefined.SetupGet (p => p.PredefinedValues).Returns (new Dictionary<string, int> {
{ "Value", GetNonDefaultRandomTestValue () },
});
predefined.SetupGet (p => p.IsConstrainedToPredefined).Returns (false);
@@ -289,7 +313,7 @@ namespace Xamarin.PropertyEditing.Tests
vm.ValueName = "test";
- var info = editor.values[property.Object] as ValueInfo<string>;
+ var info = editor.values[property.Object] as ValueInfo<int>;
Assert.That (info, Is.Not.Null);
Assert.That (info.ValueDescriptor, Is.EqualTo ("test"));
Assert.That (info.Source, Is.EqualTo (ValueSource.Local));
@@ -300,8 +324,8 @@ namespace Xamarin.PropertyEditing.Tests
public void ValueDescriptorEmptyNotNullUnconstrained ()
{
var property = GetPropertyMock ();
- var predefined = property.As<IHavePredefinedValues<string>> ();
- predefined.SetupGet (p => p.PredefinedValues).Returns (new Dictionary<string, string> {
+ var predefined = property.As<IHavePredefinedValues<int>> ();
+ predefined.SetupGet (p => p.PredefinedValues).Returns (new Dictionary<string, int> {
{ "Value", GetNonDefaultRandomTestValue () },
});
predefined.SetupGet (p => p.IsConstrainedToPredefined).Returns (false);
@@ -314,28 +338,39 @@ namespace Xamarin.PropertyEditing.Tests
vm.ValueName = "test";
vm.ValueName = null;
- var info = editor.values[property.Object] as ValueInfo<string>;
+ var info = editor.values[property.Object] as ValueInfo<int>;
Assert.That (info, Is.Not.Null);
Assert.That (info.ValueDescriptor, Is.EqualTo (String.Empty));
Assert.That (info.Source, Is.EqualTo (ValueSource.Local));
}
- protected override string GetRandomTestValue (Random rand)
+ protected override int GetRandomTestValue (Random rand)
{
- string[] names = Enum.GetNames (typeof(PredefinedEnumTest));
- int index = rand.Next (0, names.Length);
- return names[index];
+ int[] values = (int[])Enum.GetValues (typeof(PredefinedEnumTest));
+ int index = rand.Next (0, values.Length);
+ return values[index];
}
- protected override PredefinedValuesViewModel<string> GetViewModel (TargetPlatform platform, IPropertyInfo property, IEnumerable<IObjectEditor> editors)
+ protected override PredefinedValuesViewModel<int> GetViewModel (TargetPlatform platform, IPropertyInfo property, IEnumerable<IObjectEditor> editors)
{
- return new PredefinedValuesViewModel<string> (platform, property, editors);
+ return new PredefinedValuesViewModel<int> (platform, property, editors);
}
protected override bool IsConstrained => false;
- protected override IReadOnlyDictionary<string, string> Values =>
- Enum.GetNames (typeof(PredefinedEnumTest)).ToDictionary (s => s, s => s);
+ protected override IReadOnlyDictionary<string, int> Values
+ {
+ get
+ {
+ string[] names = Enum.GetNames (typeof (PredefinedEnumTest));
+ int[] values = (int[])Enum.GetValues (typeof(PredefinedEnumTest));
+ var dict = new Dictionary<string, int> ();
+ for (int i = 0; i < names.Length; i++)
+ dict.Add (names[i], values[i]);
+
+ return dict;
+ }
+ }
}
[TestFixture]
diff --git a/Xamarin.PropertyEditing.Windows/ComboBoxEx.cs b/Xamarin.PropertyEditing.Windows/ComboBoxEx.cs
new file mode 100644
index 0000000..d4369ce
--- /dev/null
+++ b/Xamarin.PropertyEditing.Windows/ComboBoxEx.cs
@@ -0,0 +1,60 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace Xamarin.PropertyEditing.Windows
+{
+ internal class ComboBoxEx
+ : ComboBox
+ {
+ static ComboBoxEx ()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata (typeof (ComboBoxEx), new FrameworkPropertyMetadata (typeof (ComboBoxEx)));
+ }
+
+ public static readonly DependencyProperty EnableSubmitProperty = DependencyProperty.Register (
+ "EnableSubmit", typeof (bool), typeof (ComboBoxEx), new PropertyMetadata (true));
+
+ public bool EnableSubmit
+ {
+ get { return (bool)GetValue (EnableSubmitProperty); }
+ set { SetValue (EnableSubmitProperty, value); }
+ }
+
+ protected override void OnSelectionChanged (SelectionChangedEventArgs e)
+ {
+ base.OnSelectionChanged (e);
+ Submit();
+ }
+
+ protected override void OnKeyDown (KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter) {
+ Submit ();
+ e.Handled = true;
+ }
+
+ base.OnKeyDown (e);
+ }
+
+ protected override void OnLostKeyboardFocus (KeyboardFocusChangedEventArgs e)
+ {
+ base.OnLostKeyboardFocus (e);
+ Submit ();
+ }
+
+ protected virtual void OnSubmit ()
+ {
+ var expression = GetBindingExpression (TextProperty);
+ expression?.UpdateSource ();
+ }
+
+ private void Submit ()
+ {
+ if (!EnableSubmit)
+ return;
+
+ OnSubmit();
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
index 75b5b92..3f61759 100644
--- a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
+++ b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
@@ -65,7 +65,7 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:EnumEditorControl}">
- <ComboBox x:Name="ComboBox" ItemsSource="{Binding PossibleValues,Mode=OneTime}" SelectedItem="{Binding ValueName}" IsEditable="{Binding IsConstrainedToPredefined,Mode=OneTime,Converter={StaticResource OppositeBoolConverter}}" VerticalContentAlignment="Center" AutomationProperties.Name="{Binding Property.Name,Mode=OneTime}" />
+ <local:ComboBoxEx x:Name="ComboBox" ItemsSource="{Binding PossibleValues,Mode=OneTime}" IsEditable="{Binding IsConstrainedToPredefined,Mode=OneTime,Converter={StaticResource OppositeBoolConverter}}" Text="{Binding ValueName,Mode=TwoWay,UpdateSourceTrigger=Explicit}" VerticalContentAlignment="Center" AutomationProperties.Name="{Binding Property.Name,Mode=OneTime}" />
</ControlTemplate>
</Setter.Value>
</Setter>
@@ -2864,4 +2864,7 @@
</Trigger>
</Style.Triggers>
</Style>
+
+ <Style TargetType="{x:Type local:ComboBoxEx}" BasedOn="{StaticResource {x:Type ComboBox}}">
+ </Style>
</ResourceDictionary>
diff --git a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
index 29b4c67..0f9563f 100644
--- a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
+++ b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
@@ -71,6 +71,7 @@
<DependentUpon>CollectionEditorWindow.xaml</DependentUpon>
</Compile>
<Compile Include="CombinablePredefinedValuesEditorControl.cs" />
+ <Compile Include="ComboBoxEx.cs" />
<Compile Include="CommonBrushToBrushConverter.cs" />
<Compile Include="ByteToPercentageConverter.cs" />
<Compile Include="ChoiceControl.cs" />
diff --git a/Xamarin.PropertyEditing/ViewModels/PredefinedValuesViewModel.cs b/Xamarin.PropertyEditing/ViewModels/PredefinedValuesViewModel.cs
index 3a6744d..2e0dbf7 100644
--- a/Xamarin.PropertyEditing/ViewModels/PredefinedValuesViewModel.cs
+++ b/Xamarin.PropertyEditing/ViewModels/PredefinedValuesViewModel.cs
@@ -38,7 +38,7 @@ namespace Xamarin.PropertyEditing.ViewModels
public string ValueName
{
get { return this.valueName; }
- set { SetValue (value); }
+ set { SetValueName (value); }
}
public bool IsConstrainedToPredefined => this.predefinedValues.IsConstrainedToPredefined;
@@ -64,7 +64,7 @@ namespace Xamarin.PropertyEditing.ViewModels
private string valueName;
private readonly IHavePredefinedValues<TValue> predefinedValues;
- private async void SetValue (string value)
+ private async void SetValueName (string value)
{
if (value == this.valueName)
return;
@@ -84,9 +84,6 @@ namespace Xamarin.PropertyEditing.ViewModels
});
} else
Value = realValue;
-
- this.valueName = value;
- OnPropertyChanged ();
}
private bool IsValueDefined (TValue value)
@@ -113,6 +110,10 @@ namespace Xamarin.PropertyEditing.ViewModels
if (ValueSource == ValueSource.Unset) {
this.valueName = String.Empty;
OnPropertyChanged (nameof(ValueName));
+ // Order relevant: Value may default() to a valid value, so ValueDescriptor takes precedence
+ } else if (!IsConstrainedToPredefined && CurrentValue != null && CurrentValue.ValueDescriptor is string custom) {
+ this.valueName = custom;
+ OnPropertyChanged (nameof (ValueName));
} else if (TryGetValueName (Value, out string newValueName)) {
this.valueName = newValueName;
OnPropertyChanged (nameof(ValueName));