Browse Source

Merge branch 'master' into routedevent-fixes

Jumar Macato 6 years ago
parent
commit
4c4d649380

+ 38 - 13
src/Avalonia.Base/AvaloniaObject.cs

@@ -208,20 +208,9 @@ namespace Avalonia
             {
                 return ((IDirectPropertyAccessor)GetRegistered(property)).GetValue(this);
             }
-            else if (_values != null)
-            {
-                var result = Values.GetValue(property);
-
-                if (result == AvaloniaProperty.UnsetValue)
-                {
-                    result = GetDefaultValue(property);
-                }
-
-                return result;
-            }
             else
             {
-                return GetDefaultValue(property);
+                return GetValueOrDefaultUnchecked(property);
             }
         }
 
@@ -598,10 +587,46 @@ namespace Avalonia
         private object GetDefaultValue(AvaloniaProperty property)
         {
             if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
-                return aobj.GetValue(property);
+                return aobj.GetValueOrDefaultUnchecked(property);
             return ((IStyledPropertyAccessor) property).GetDefaultValue(GetType());
         }
 
+        /// <summary>
+        /// Gets the value or default value for a property.
+        /// </summary>
+        /// <param name="property">The property.</param>
+        /// <returns>The default value.</returns>
+        private object GetValueOrDefaultUnchecked(AvaloniaProperty property)
+        {
+            var aobj = this;
+            var valuestore = aobj._values;
+            if (valuestore != null)
+            {
+                var result = valuestore.GetValue(property);
+                if (result != AvaloniaProperty.UnsetValue)
+                {
+                    return result;
+                }
+            }
+            if (property.Inherits)
+            {
+                while (aobj.InheritanceParent is AvaloniaObject parent)
+                {
+                    aobj = parent;
+                    valuestore = aobj._values;
+                    if (valuestore != null)
+                    {
+                        var result = valuestore.GetValue(property);
+                        if (result != AvaloniaProperty.UnsetValue)
+                        {
+                            return result;
+                        }
+                    }
+                }
+            }
+            return ((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
+        }
+
         /// <summary>
         /// Sets the value of a direct property.
         /// </summary>

+ 2 - 2
src/Avalonia.Controls.DataGrid/Themes/Default.xaml

@@ -217,12 +217,12 @@
             <DataGridRowsPresenter Name="PART_RowsPresenter" Grid.ColumnSpan="2" Grid.Row="1" />
             <Rectangle Name="BottomRightCorner" Fill="#FFE9EEF4" Grid.Column="2" Grid.Row="2" />
             <Rectangle Name="BottomLeftCorner" Fill="#FFE9EEF4" Grid.Row="2" Grid.ColumnSpan="2" />
-            <ScrollBar Name="PART_VerticalScrollbar" Orientation="Vertical" Grid.Column="2" Grid.Row="1" Width="18" Margin="0,-1,-1,-1"/>
+            <ScrollBar Name="PART_VerticalScrollbar" Orientation="Vertical" Grid.Column="2" Grid.Row="1" Width="{DynamicResource ScrollBarThickness}" Margin="0,-1,-1,-1"/>
 
             <Grid Grid.Column="1" Grid.Row="2"
                   ColumnDefinitions="Auto,*">
               <Rectangle Name="PART_FrozenColumnScrollBarSpacer" />
-              <ScrollBar Name="PART_HorizontalScrollbar" Grid.Column="1" Orientation="Horizontal" Height="18" Margin="-1,0,-1,-1"/>
+              <ScrollBar Name="PART_HorizontalScrollbar" Grid.Column="1" Orientation="Horizontal" Height="{DynamicResource ScrollBarThickness}" Margin="-1,0,-1,-1"/>
             </Grid>
           </Grid>
         </Border>

+ 1 - 1
src/Avalonia.Input/Gestures.cs

@@ -31,7 +31,7 @@ namespace Avalonia.Input
             RoutedEvent.Register<ScrollGestureEventArgs>(
                 "ScrollGestureEnded", RoutingStrategies.Bubble, typeof(Gestures));
 
-        private static WeakReference<IInteractive> s_lastPress;
+        private static WeakReference<IInteractive> s_lastPress = new WeakReference<IInteractive>(null);
 
         static Gestures()
         {

+ 6 - 6
src/Markup/Avalonia.Markup/Data/MultiBinding.cs

@@ -76,7 +76,12 @@ namespace Avalonia.Data
             }
             
             var children = Bindings.Select(x => x.Initiate(target, null));
-            var input = children.Select(x => x.Observable).CombineLatest().Select(x => ConvertValue(x, targetType, converter));
+
+            var input = children.Select(x => x.Observable)
+                                .CombineLatest()
+                                .Select(x => ConvertValue(x, targetType, converter))
+                                .Where(x => x != BindingOperations.DoNothing);
+
             var mode = Mode == BindingMode.Default ?
                 targetProperty?.GetMetadata(target.GetType()).DefaultBindingMode : Mode;
 
@@ -97,11 +102,6 @@ namespace Avalonia.Data
             var culture = CultureInfo.CurrentCulture;
             var converted = converter.Convert(values, targetType, ConverterParameter, culture);
 
-            if (converted == BindingOperations.DoNothing)
-            {
-                return converted;
-            }
-
             if (converted == AvaloniaProperty.UnsetValue)
             {
                 converted = FallbackValue;

+ 76 - 0
tests/Avalonia.Markup.Xaml.UnitTests/Converters/MultiValueConverterTests.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Data.Converters;
+using Avalonia.UnitTests;
+using Xunit;
+
+namespace Avalonia.Markup.Xaml.UnitTests.Converters
+{
+    public class MultiValueConverterTests : XamlTestBase
+    {
+        [Fact]
+        public void MultiValueConverter_Special_Values_Work()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:c='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Converters;assembly=Avalonia.Markup.Xaml.UnitTests'>
+    <TextBlock Name='textBlock'>
+        <TextBlock.Text>
+            <MultiBinding Converter='{x:Static c:TestMultiValueConverter.Instance}' FallbackValue='bar'>
+                <Binding Path='Item1' />
+                <Binding Path='Item2' />
+            </MultiBinding>
+        </TextBlock.Text>
+    </TextBlock>
+</Window>";
+                var loader = new AvaloniaXamlLoader();
+                var window = (Window)loader.Load(xaml);
+                var textBlock = window.FindControl<TextBlock>("textBlock");
+
+                window.ApplyTemplate();
+
+                window.DataContext = Tuple.Create(2, 2);
+                Assert.Equal("foo", textBlock.Text);
+
+                window.DataContext = Tuple.Create(-3, 3);
+                Assert.Equal("foo", textBlock.Text);
+
+                window.DataContext = Tuple.Create(0, 2);
+                Assert.Equal("bar", textBlock.Text);
+            }
+        }
+    }
+
+    public class TestMultiValueConverter : IMultiValueConverter
+    {
+        public static readonly TestMultiValueConverter Instance = new TestMultiValueConverter();
+
+        public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (values[0] is int i && values[1] is int j)
+            {
+                var p = i * j;
+
+                if (p > 0)
+                {
+                    return "foo";
+                }
+
+                if (p == 0)
+                {
+                    return AvaloniaProperty.UnsetValue;
+                }
+
+                return BindingOperations.DoNothing;
+            }
+
+            return "(default)";
+        }
+    }
+}