Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify TemplateBindings #1695

Merged
merged 5 commits into from
Jul 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions samples/ControlCatalog/SideBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<TabStrip Name="PART_TabStrip"
MemberSelector="{x:Static TabControl.HeaderSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex, Mode=TwoWay}">
SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabStrip.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
Expand All @@ -20,7 +20,7 @@
Margin="8 0 0 0"
MemberSelector="{x:Static TabControl.ContentSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex}"
SelectedIndex="{TemplateBinding SelectedIndex}"
PageTransition="{TemplateBinding PageTransition}"
Grid.Row="1"/>
</DockPanel>
Expand Down
4 changes: 2 additions & 2 deletions samples/RenderDemo/SideBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<TabStrip Name="PART_TabStrip"
MemberSelector="{x:Static TabControl.HeaderSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex, Mode=TwoWay}">
SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabStrip.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
Expand All @@ -21,7 +21,7 @@
Margin="8 0 0 0"
MemberSelector="{x:Static TabControl.ContentSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex}"
SelectedIndex="{TemplateBinding SelectedIndex}"
PageTransition="{TemplateBinding PageTransition}"
Grid.Row="1"/>
</DockPanel>
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Themes.Default/AutoCompleteBox.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}" />

<Popup Name="PART_Popup"
MinWidth="{TemplateBinding Bounds.Width}"
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
PlacementTarget="{TemplateBinding}"
StaysOpen="False">
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Themes.Default/DropDown.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</ToggleButton>
<Popup Name="PART_Popup"
IsOpen="{TemplateBinding IsDropDownOpen, Mode=TwoWay}"
MinWidth="{TemplateBinding Bounds.Width}"
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
PlacementTarget="{TemplateBinding}"
StaysOpen="False">
Expand Down
4 changes: 2 additions & 2 deletions src/Avalonia.Themes.Default/MenuItem.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<Popup Name="PART_Popup"
PlacementMode="Right"
StaysOpen="True"
IsOpen="{TemplateBinding Path=IsSubMenuOpen, Mode=TwoWay}"
IsOpen="{TemplateBinding IsSubMenuOpen, Mode=TwoWay}"
ObeyScreenEdges="True">
<Border Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource ThemeBorderMidBrush}"
Expand Down Expand Up @@ -92,7 +92,7 @@
</ContentPresenter.DataTemplates>
</ContentPresenter>
<Popup Name="PART_Popup"
IsOpen="{TemplateBinding Path=IsSubMenuOpen, Mode=TwoWay}"
IsOpen="{TemplateBinding IsSubMenuOpen, Mode=TwoWay}"
StaysOpen="True"
ObeyScreenEdges="True">
<Border Background="{TemplateBinding Background}"
Expand Down
4 changes: 2 additions & 2 deletions src/Avalonia.Themes.Default/ScrollBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
Grid.Column="1"
Minimum="{TemplateBinding Minimum}"
Maximum="{TemplateBinding Maximum}"
Value="{TemplateBinding Path=Value, Mode=TwoWay}"
Value="{TemplateBinding Value, Mode=TwoWay}"
ViewportSize="{TemplateBinding ViewportSize}"
Orientation="{TemplateBinding Orientation}">
<Track.DecreaseButton>
Expand Down Expand Up @@ -67,7 +67,7 @@
Grid.Column="1"
Minimum="{TemplateBinding Minimum}"
Maximum="{TemplateBinding Maximum}"
Value="{TemplateBinding Path=Value, Mode=TwoWay}"
Value="{TemplateBinding Value, Mode=TwoWay}"
ViewportSize="{TemplateBinding ViewportSize}"
Orientation="{TemplateBinding Orientation}">
<Track.DecreaseButton>
Expand Down
10 changes: 5 additions & 5 deletions src/Avalonia.Themes.Default/ScrollViewer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}"
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}"
Content="{TemplateBinding Content}"
Extent="{TemplateBinding Path=Extent, Mode=TwoWay}"
Extent="{TemplateBinding Extent, Mode=TwoWay}"
Margin="{TemplateBinding Padding}"
Offset="{TemplateBinding Path=Offset, Mode=TwoWay}"
Viewport="{TemplateBinding Path=Viewport, Mode=TwoWay}"/>
Offset="{TemplateBinding Offset, Mode=TwoWay}"
Viewport="{TemplateBinding Viewport, Mode=TwoWay}"/>
<ScrollBar Name="horizontalScrollBar"
Orientation="Horizontal"
Maximum="{TemplateBinding HorizontalScrollBarMaximum}"
Value="{TemplateBinding Path=HorizontalScrollBarValue, Mode=TwoWay}"
Value="{TemplateBinding HorizontalScrollBarValue, Mode=TwoWay}"
ViewportSize="{TemplateBinding HorizontalScrollBarViewportSize}"
Visibility="{TemplateBinding HorizontalScrollBarVisibility}"
Grid.Row="1"/>
<ScrollBar Name="verticalScrollBar"
Orientation="Vertical"
Maximum="{TemplateBinding VerticalScrollBarMaximum}"
Value="{TemplateBinding Path=VerticalScrollBarValue, Mode=TwoWay}"
Value="{TemplateBinding VerticalScrollBarValue, Mode=TwoWay}"
ViewportSize="{TemplateBinding VerticalScrollBarViewportSize}"
Visibility="{TemplateBinding VerticalScrollBarVisibility}"
Grid.Column="1"/>
Expand Down
7 changes: 3 additions & 4 deletions src/Avalonia.Themes.Default/Slider.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Name="TrackBackground" Grid.Row="1" Height="4" Margin="6,0" VerticalAlignment="Center"/>
<Track Name="PART_Track" Grid.Row="1">
<Track Name="PART_Track" Grid.Row="1" Orientation="Horizontal">
<Track.DecreaseButton>
<RepeatButton Name="PART_DecreaseButton"
Classes="repeattrack" />
Expand Down Expand Up @@ -46,7 +46,7 @@
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Name="TrackBackground" Grid.Column="1" Width="4" Margin="0,6" HorizontalAlignment="Center"/>
<Track Name="PART_Track" Grid.Column="1">
<Track Name="PART_Track" Grid.Column="1" Orientation="Vertical">
<Track.DecreaseButton>
<RepeatButton Name="PART_DecreaseButton"
Classes="repeattrack" />
Expand All @@ -72,8 +72,7 @@
<Style Selector="Slider /template/ Track#PART_Track">
<Setter Property="Minimum" Value="{TemplateBinding Minimum}"/>
<Setter Property="Maximum" Value="{TemplateBinding Maximum}"/>
<Setter Property="Value" Value="{TemplateBinding Path=Value, Mode=TwoWay}"/>
<Setter Property="Orientation" Value="{TemplateBinding Orientation}"/>
<Setter Property="Value" Value="{TemplateBinding Value, Mode=TwoWay}"/>
Copy link
Member Author

@grokys grokys Jun 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setter was both unnecessary and caused problems in that it was binding to Track.Orientation instead of Slider.Orientation which are actually different AvaloniaPropertys (#1696). This was resulting in the Slider getting messed up.

</Style>
<Style Selector="Slider /template/ Border#TrackBackground">
<Setter Property="BorderThickness" Value="2"/>
Expand Down
4 changes: 2 additions & 2 deletions src/Avalonia.Themes.Default/TabControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
<TabStrip Name="PART_TabStrip"
MemberSelector="{x:Static TabControl.HeaderSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex, Mode=TwoWay}"/>
SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}"/>
<Carousel Name="PART_Content"
MemberSelector="{x:Static TabControl.ContentSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex}"
SelectedIndex="{TemplateBinding SelectedIndex}"
PageTransition="{TemplateBinding PageTransition}"
Grid.Row="1"/>
</DockPanel>
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Themes.Default/TextBox.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<TextBlock Name="watermark"
Opacity="0.5"
Text="{TemplateBinding Watermark}"
IsVisible="{TemplateBinding Path=Text, Converter={x:Static StringConverters.NullOrEmpty}}"/>
IsVisible="{TemplateBinding Text, Converter={x:Static StringConverters.NullOrEmpty}}"/>
<TextPresenter Name="PART_TextPresenter"
Text="{TemplateBinding Text, Mode=TwoWay}"
CaretIndex="{TemplateBinding CaretIndex}"
Expand Down
4 changes: 1 addition & 3 deletions src/Avalonia.Themes.Default/TreeViewItem.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
<Grid ColumnDefinitions="16, Auto">
<ToggleButton Name="expander"
Focusable="False"
IsChecked="{TemplateBinding Path=IsExpanded, Mode=TwoWay}"/>
IsChecked="{TemplateBinding IsExpanded, Mode=TwoWay}"/>
<ContentPresenter Name="PART_HeaderPresenter"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Header}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Padding="{TemplateBinding Padding}"
TemplatedControl.IsTemplateFocusTarget="True"
Grid.Column="1"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
<Compile Include="Converters\SelectorTypeConverter.cs" />
<Compile Include="MarkupExtensions\BindingExtension.cs" />
<Compile Include="MarkupExtensions\RelativeSourceExtension.cs" />
<Compile Include="MarkupExtensions\TemplateBindingExtension.cs" />
<Compile Include="PortableXaml\AvaloniaTypeAttributeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaXamlType.cs" />
<Compile Include="PortableXaml\TypeDescriptorExtensions.cs" />
Expand Down
2 changes: 1 addition & 1 deletion src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public object Load(Uri uri, Uri baseUri = null, object rootInstance = null)
{
uriString = new Uri(baseUri, uri).AbsoluteUri;
}
throw new XamlLoadException("Error loading xaml at " + uriString, e);
throw new XamlLoadException("Error loading xaml at " + uriString + ": " + e.Message, e);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fixed the annoying problem where the XAML exception message didn't actually include the description of what went wrong.

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,80 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Styling;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using Portable.Xaml.Markup;

namespace Avalonia.Markup.Xaml.Converters
{
using Avalonia.Styling;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using System.ComponentModel;
using Portable.Xaml.Markup;

public class AvaloniaPropertyTypeConverter : TypeConverter
{
private static readonly Regex regex = new Regex(@"^\(?(\w*)\.(\w*)\)?|(.*)$");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows attached properties to be optionally specified with braces surrounding the property, as in a standard Binding.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way we can do this without using regular expressions? Regex uses lot of memory for us just checking if the string starts and ends with parentheses.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah definitely! I looked at using StringTokenizer for this, but it wasn't suitable, and I didn't want to introduce another string tokenizer in this PR. Wasn't sure if we should make StringTokenizer more general purpose, or just manually parse the string here, so I just used Regex for the time being.


public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var s = (string)value;
var (owner, propertyName) = ParseProperty((string)value);
var ownerType = TryResolveOwnerByName(context, owner) ??
context.GetFirstAmbientValue<ControlTemplate>()?.TargetType ??
context.GetFirstAmbientValue<Style>()?.Selector?.TargetType;

string typeName;
string propertyName;
Type type = null;
if (ownerType == null)
{
throw new XamlLoadException(
$"Could not determine the owner type for property '{propertyName}'. " +
"Please fully qualify the property name or specify a target type on " +
"the containing template.");
}

ParseProperty(s, out typeName, out propertyName);
var property = AvaloniaPropertyRegistry.Instance.FindRegistered(ownerType, propertyName);

if (typeName == null)
if (property == null)
{
var style = context.GetFirstAmbientValue<Style>();
throw new XamlLoadException($"Could not find AvaloniaProperty '{ownerType.Name}.{propertyName}'.");
}

type = style?.Selector?.TargetType;
return property;
}

if (type == null)
{
throw new Exception(
"Could not determine the target type. Please fully qualify the property name.");
}
}
else
private Type TryResolveOwnerByName(ITypeDescriptorContext context, string owner)
{
if (owner != null)
{
var typeResolver = context.GetService<IXamlTypeResolver>();
type = typeResolver.Resolve(typeName);
var resolver = context.GetService<IXamlTypeResolver>();
var result = resolver.Resolve(owner);

if (type == null)
if (result == null)
{
throw new Exception($"Could not find type '{typeName}'.");
throw new XamlLoadException($"Could not find type '{owner}'.");
}
}

AvaloniaProperty property = AvaloniaPropertyRegistry.Instance.FindRegistered(type, propertyName);

if (property == null)
{
throw new Exception(
$"Could not find AvaloniaProperty '{type.Name}.{propertyName}'.");
return result;
}

return property;
return null;
}

private void ParseProperty(string s, out string typeName, out string propertyName)
private (string owner, string property) ParseProperty(string s)
{
var split = s.Split('.');
var result = regex.Match(s);

if (split.Length == 1)
{
typeName = null;
propertyName = split[0];
}
else if (split.Length == 2)
if (result.Groups[1].Success)
{
typeName = split[0];
propertyName = split[1];
return (result.Groups[1].Value, result.Groups[2].Value);
}
else
{
throw new Exception($"Invalid property name: '{s}'.");
return (null, result.Groups[3].Value);
}
}
}
Expand Down

This file was deleted.

Loading