Browse Source

Added DropDown theme in XAML.

Something weird is happening where selected items are removed from the
tree somehow.
Steven Kirk 10 years ago
parent
commit
d54772033b

+ 7 - 6
samples/XamlTestApplicationPcl/DropDown.paml

@@ -1,7 +1,7 @@
 <Styles xmlns="https://github.com/perspex">
   <Style Selector="DropDown">
-    <Setter Property="BorderBrush" Value="Black"/>
-    <Setter Property="BorderThickness" Value="1"/>
+    <Setter Property="BorderBrush" Value="#ff707070"/>
+    <Setter Property="BorderThickness" Value="2"/>
     <Setter Property="HorizontalContentAlignment" Value="Center"/>
     <Setter Property="VerticalContentAlignment" Value="Center"/>
     <Setter Property="Template">
@@ -18,15 +18,15 @@
                           BorderThickness="0"
                           Background="Transparent"
                           ClickMode="Press"
-                          Focusable="False">
+                          Focusable="False"
+                          Grid.Column="1">
               <Path Fill="Black"
                     Width="8"
                     Height="4"
                     Stretch="Uniform"
                     HorizontalAlignment="Center"
                     VerticalAlignment="Center"
-                    Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z"
-                    Grid.Column="1"/>
+                    Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z"/>
             </ToggleButton>
             <Popup Name="PART_Popup"
                    IsOpen="{TemplateBinding Path=IsDropDownOpen, Mode=TwoWay}"
@@ -36,7 +36,8 @@
               <Border BorderBrush="Black"
                       BorderThickness="1"
                       Padding="4">
-                <ItemsPresenter Items="{TemplateBinding Items}" 
+                <ItemsPresenter Name="PART_ItemsPresenter"
+                                Items="{TemplateBinding Items}" 
                                 MemberSelector="{TemplateBinding MemberSelector}"/>
               </Border>
             </Popup>

+ 11 - 0
samples/XamlTestApplicationPcl/PopupRoot.paml

@@ -0,0 +1,11 @@
+<Style xmlns="https://github.com/perspex" Selector="PopupRoot">
+  <Setter Property="Template">
+    <ControlTemplate>
+      <Border Background="{TemplateBinding Background}">
+        <ContentPresenter Name="PART_ContentPresenter" 
+                          Content="{TemplateBinding Content}" 
+                          Margin="{TemplateBinding Padding}"/>
+      </Border>
+    </ControlTemplate>
+  </Setter>
+</Style>

+ 1 - 1
samples/XamlTestApplicationPcl/Window.paml

@@ -5,7 +5,7 @@
     <ControlTemplate>
       <Border Background="{TemplateBinding Background}">
         <AdornerDecorator>
-          <ContentPresenter Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
+          <ContentPresenter Name="PART_ContentPresenter" Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
         </AdornerDecorator>
       </Border>
     </ControlTemplate>

+ 1 - 0
samples/XamlTestApplicationPcl/XamlTestApp.paml

@@ -10,6 +10,7 @@
     <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.ItemsControl.paml"/>
     <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.ListBox.paml"/>
     <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.ListBoxItem.paml"/>
+    <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.PopupRoot.paml"/>
     <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.RadioButton.paml"/>
     <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.ScrollBar.paml"/>
     <StyleInclude Source="resource://application/XamlTestApplicationPcl/XamlTestApplication.ScrollViewer.paml"/>

+ 3 - 0
samples/XamlTestApplicationPcl/XamlTestApplicationPcl.csproj

@@ -188,6 +188,9 @@
     <EmbeddedResource Include="ContentControl.paml">
       <SubType>Designer</SubType>
     </EmbeddedResource>
+    <EmbeddedResource Include="PopupRoot.paml">
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
   </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 8 - 2
src/Markup/Perspex.Markup.Xaml/Data/Binding.cs

@@ -102,7 +102,7 @@ namespace Perspex.Markup.Xaml.Data
             {
                 var result = new ExpressionObserver(
                     () => dataContextHost.GetValue(Control.DataContextProperty),
-                    SourcePropertyPath);
+                    GetExpression());
                 dataContextHost.GetObservable(Control.DataContextProperty).Subscribe(x =>
                     result.UpdateRoot());
                 return result;
@@ -117,7 +117,7 @@ namespace Perspex.Markup.Xaml.Data
         {
             var result = new ExpressionObserver(
                 () => instance.GetValue(Control.TemplatedParentProperty),
-                SourcePropertyPath);
+                GetExpression());
 
             if (instance.GetValue(Control.TemplatedParentProperty) == null)
             {
@@ -131,5 +131,11 @@ namespace Perspex.Markup.Xaml.Data
 
             return result;
         }
+
+        private string GetExpression()
+        {
+            return SourcePropertyPath == null || SourcePropertyPath == "." ?
+                string.Empty : SourcePropertyPath;
+        }
     }
 }

+ 35 - 9
src/Markup/Perspex.Markup/Data/ExpressionObserver.cs

@@ -5,6 +5,7 @@ using System;
 using System.Collections.Generic;
 using System.Reactive;
 using System.Reactive.Disposables;
+using System.Reactive.Subjects;
 using Perspex.Markup.Data.Plugins;
 
 namespace Perspex.Markup.Data
@@ -28,6 +29,7 @@ namespace Perspex.Markup.Data
         private Func<object> _root;
         private int _count;
         private ExpressionNode _node;
+        private ISubject<object> _empty;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ExpressionObserver"/> class.
@@ -50,7 +52,12 @@ namespace Perspex.Markup.Data
             Contract.Requires<ArgumentNullException>(expression != null);
 
             _root = root;
-            _node = ExpressionNodeBuilder.Build(expression);
+
+            if (!string.IsNullOrWhiteSpace(expression))
+            {
+                _node = ExpressionNodeBuilder.Build(expression);
+            }
+
             Expression = expression;
         }
 
@@ -126,7 +133,14 @@ namespace Perspex.Markup.Data
         {
             if (_count > 0)
             {
-                _node.Target = _root();
+                if (_node != null)
+                {
+                    _node.Target = _root();
+                }
+                else if (_empty != null)
+                {
+                    _empty.OnNext(_root());
+                }
             }
         }
 
@@ -135,18 +149,30 @@ namespace Perspex.Markup.Data
         {
             IncrementCount();
 
-            var subscription = _node.Subscribe(observer);
+            if (_node != null)
+            {
+                var subscription = _node.Subscribe(observer);
 
-            return Disposable.Create(() =>
+                return Disposable.Create(() =>
+                {
+                    DecrementCount();
+                    subscription.Dispose();
+                });
+            }
+            else
             {
-                DecrementCount();
-                subscription.Dispose();
-            });
+                if (_empty == null)
+                {
+                    _empty = new BehaviorSubject<object>(_root());
+                }
+
+                return _empty.Subscribe(observer);
+            }
         }
 
         private void IncrementCount()
         {
-            if (_count++ == 0)
+            if (_count++ == 0 && _node != null)
             {
                 _node.Target = _root();
             }
@@ -154,7 +180,7 @@ namespace Perspex.Markup.Data
 
         private void DecrementCount()
         {
-            if (--_count == 0)
+            if (--_count == 0 && _node != null)
             {
                 _node.Target = null;
             }

+ 2 - 2
src/Perspex.Controls/DropDown.cs

@@ -132,7 +132,7 @@ namespace Perspex.Controls
                 _popup.Opened -= PopupOpened;
             }
 
-            _popup = this.GetTemplateChild<Popup>("popup");
+            _popup = this.GetTemplateChild<Popup>("PART_Popup");
             _popup.Opened += PopupOpened;
         }
 
@@ -143,7 +143,7 @@ namespace Perspex.Controls
             if (selectedIndex != -1)
             {
                 var container = ItemContainerGenerator.ContainerFromIndex(selectedIndex);
-                container.Focus();
+                container?.Focus();
             }
         }
 

+ 15 - 0
tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests_Property.cs

@@ -188,6 +188,21 @@ namespace Perspex.Markup.UnitTests.Binding
             Assert.Equal(0, old.SubscriptionCount);
         }
 
+        [Fact]
+        public void Empty_Expression_Should_Track_Root()
+        {
+            var data = new Class1 { Foo = "foo" };
+            var target = new ExpressionObserver(() => data.Foo, "");
+            var result = new List<object>();
+
+            target.Subscribe(x => result.Add(x));
+
+            data.Foo = "bar";
+            target.UpdateRoot();
+
+            Assert.Equal(new[] { "foo", "bar" }, result);
+        }
+
         [Fact]
         public void SetValue_Should_Set_Simple_Property_Value()
         {