зеркало из https://github.com/DeGsoft/maui-linux.git
[WPF] Xamarin Forms WPF Backend - Platform Project (#1334)
* Add WPF Platform, WPF const in Device and Update Docs * Add Settings.Designer.cs * Remove two lines : build on iPhone configuration * Remove lines for ios build
This commit is contained in:
Родитель
6d89f8429e
Коммит
1bbd9dfa52
|
@ -17,6 +17,7 @@ namespace Xamarin.Forms
|
|||
public const string macOS = "macOS";
|
||||
public const string GTK = "GTK";
|
||||
public const string Tizen = "Tizen";
|
||||
public const string WPF = "WPF";
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static DeviceInfo info;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal class Animatable : IAnimatable
|
||||
{
|
||||
public void BatchBegin()
|
||||
{
|
||||
}
|
||||
|
||||
public void BatchCommit()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class CellControl : ContentControl
|
||||
{
|
||||
public static readonly DependencyProperty CellProperty = DependencyProperty.Register("Cell", typeof(object), typeof(CellControl),
|
||||
new PropertyMetadata((o, e) => ((CellControl)o).SetSource(e.OldValue, e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty ShowContextActionsProperty = DependencyProperty.Register("ShowContextActions", typeof(bool), typeof(CellControl), new PropertyMetadata(true));
|
||||
|
||||
readonly PropertyChangedEventHandler _propertyChangedHandler;
|
||||
|
||||
public CellControl()
|
||||
{
|
||||
Unloaded += (sender, args) =>
|
||||
{
|
||||
ICellController cell = DataContext as ICellController;
|
||||
if (cell != null)
|
||||
cell.SendDisappearing();
|
||||
};
|
||||
|
||||
_propertyChangedHandler = OnCellPropertyChanged;
|
||||
}
|
||||
|
||||
public Cell Cell
|
||||
{
|
||||
get { return (Cell)GetValue(CellProperty); }
|
||||
set { SetValue(CellProperty, value); }
|
||||
}
|
||||
|
||||
public bool ShowContextActions
|
||||
{
|
||||
get { return (bool)GetValue(ShowContextActionsProperty); }
|
||||
set { SetValue(ShowContextActionsProperty, value); }
|
||||
}
|
||||
|
||||
System.Windows.DataTemplate GetTemplate(Cell cell)
|
||||
{
|
||||
var renderer = Registrar.Registered.GetHandler<ICellRenderer>(cell.GetType());
|
||||
return renderer.GetTemplate(cell);
|
||||
}
|
||||
|
||||
void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "HasContextActions")
|
||||
SetupContextMenu();
|
||||
}
|
||||
|
||||
void SetSource(object oldCellObj, object newCellObj)
|
||||
{
|
||||
|
||||
var oldCell = oldCellObj as Cell;
|
||||
var newCell = newCellObj as Cell;
|
||||
|
||||
if (oldCell != null)
|
||||
{
|
||||
oldCell.PropertyChanged -= _propertyChangedHandler;
|
||||
((ICellController)oldCell).SendDisappearing();
|
||||
}
|
||||
|
||||
if (newCell != null)
|
||||
{
|
||||
((ICellController)newCell).SendAppearing();
|
||||
|
||||
if (oldCell == null || oldCell.GetType() != newCell.GetType())
|
||||
ContentTemplate = GetTemplate(newCell);
|
||||
|
||||
Content = newCell;
|
||||
|
||||
SetupContextMenu();
|
||||
|
||||
newCell.PropertyChanged += _propertyChangedHandler;
|
||||
}
|
||||
else
|
||||
Content = null;
|
||||
}
|
||||
|
||||
void SetupContextMenu()
|
||||
{
|
||||
if (Content == null || !ShowContextActions)
|
||||
return;
|
||||
|
||||
if (!Cell.HasContextActions)
|
||||
{
|
||||
ContextMenuService.SetContextMenu(this, null);
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyTemplate();
|
||||
|
||||
ContextMenu menu = new CustomContextMenu();
|
||||
menu.SetBinding(ItemsControl.ItemsSourceProperty, new System.Windows.Data.Binding("ContextActions"));
|
||||
|
||||
ContextMenuService.SetContextMenu(this, menu);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class CaseConverter : System.Windows.Data.IValueConverter
|
||||
{
|
||||
public bool ConvertToUpper { get; set; }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
var v = (string)value;
|
||||
return ConvertToUpper ? v.ToUpper() : v.ToLower();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class CollapseWhenEmptyConverter : System.Windows.Data.IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var length = 0;
|
||||
|
||||
string s = value as string;
|
||||
if (s != null)
|
||||
length = s.Length;
|
||||
|
||||
if (value is int)
|
||||
length = (int)value;
|
||||
|
||||
return length > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class ColorConverter : System.Windows.Data.IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
FrameworkElement framework = values[0] as FrameworkElement;
|
||||
DependencyProperty dp = parameter as DependencyProperty;
|
||||
|
||||
if (values.Count() > 1 && framework != null && values[1] is Color && dp != null)
|
||||
{
|
||||
return framework.UpdateDependencyColor(dp, (Color)values[1]);
|
||||
}
|
||||
return Color.Transparent.ToBrush();
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class HeightConverter : System.Windows.Data.IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var ps = parameter as string;
|
||||
double def;
|
||||
if (string.IsNullOrWhiteSpace(ps) || !double.TryParse(ps, out def))
|
||||
{
|
||||
def = double.NaN;
|
||||
}
|
||||
|
||||
var val = (double)value;
|
||||
return val > 0 ? val : def;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class ImageConverter : System.Windows.Data.IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var source = (ImageSource)value;
|
||||
IImageSourceHandler handler;
|
||||
|
||||
if (source != null && (handler = Internals.Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
|
||||
{
|
||||
Task<System.Windows.Media.ImageSource> image = handler.LoadImageAsync(source);
|
||||
image.Wait();
|
||||
return image.Result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class ViewToRendererConverter : System.Windows.Data.IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
VisualElement visualElement = value as VisualElement;
|
||||
if (visualElement != null)
|
||||
{
|
||||
var frameworkElement = Platform.GetOrCreateRenderer(visualElement)?.GetNativeElement();
|
||||
|
||||
if(frameworkElement != null)
|
||||
{
|
||||
frameworkElement.Loaded += (sender, args) =>
|
||||
{
|
||||
visualElement.Layout(new Rectangle(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight));
|
||||
};
|
||||
|
||||
frameworkElement.SizeChanged += (sender, args) =>
|
||||
{
|
||||
visualElement.Layout(new Rectangle(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight));
|
||||
};
|
||||
|
||||
return frameworkElement;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using WMenuItem = System.Windows.Controls.MenuItem;
|
||||
using WApplication = System.Windows.Application;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public sealed class CustomContextMenu : ContextMenu
|
||||
{
|
||||
protected override DependencyObject GetContainerForItemOverride()
|
||||
{
|
||||
var item = new WMenuItem();
|
||||
item.SetBinding(HeaderedItemsControl.HeaderProperty, new System.Windows.Data.Binding("Text"));
|
||||
|
||||
item.Click += (sender, args) =>
|
||||
{
|
||||
IsOpen = false;
|
||||
|
||||
var menuItem = item.DataContext as MenuItem;
|
||||
if (menuItem != null)
|
||||
((IMenuItemController)menuItem).Activate();
|
||||
};
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class VisualElementChangedEventArgs : ElementChangedEventArgs<VisualElement>
|
||||
{
|
||||
public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) : base(oldElement, newElement)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ElementChangedEventArgs<TElement> : EventArgs where TElement : Element
|
||||
{
|
||||
public ElementChangedEventArgs(TElement oldElement, TElement newElement)
|
||||
{
|
||||
OldElement = oldElement;
|
||||
NewElement = newElement;
|
||||
}
|
||||
|
||||
public TElement NewElement { get; private set; }
|
||||
|
||||
public TElement OldElement { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class ExportRendererAttribute : HandlerAttribute
|
||||
{
|
||||
public ExportRendererAttribute(Type handler, Type target) : base(handler, target)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class ExportCellAttribute : HandlerAttribute
|
||||
{
|
||||
public ExportCellAttribute(Type handler, Type target) : base(handler, target)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute
|
||||
{
|
||||
public ExportImageSourceHandlerAttribute(Type handler, Type target) : base(handler, target)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal static class AlignmentExtensions
|
||||
{
|
||||
internal static System.Windows.TextAlignment ToNativeTextAlignment(this TextAlignment alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case TextAlignment.Center:
|
||||
return System.Windows.TextAlignment.Center;
|
||||
case TextAlignment.End:
|
||||
return System.Windows.TextAlignment.Right;
|
||||
default:
|
||||
return System.Windows.TextAlignment.Left;
|
||||
}
|
||||
}
|
||||
|
||||
internal static VerticalAlignment ToNativeVerticalAlignment(this LayoutOptions alignment)
|
||||
{
|
||||
switch (alignment.Alignment)
|
||||
{
|
||||
case LayoutAlignment.Start:
|
||||
return VerticalAlignment.Top;
|
||||
case LayoutAlignment.Center:
|
||||
return VerticalAlignment.Center;
|
||||
case LayoutAlignment.End:
|
||||
return VerticalAlignment.Bottom;
|
||||
case LayoutAlignment.Fill:
|
||||
return VerticalAlignment.Stretch;
|
||||
default:
|
||||
return VerticalAlignment.Stretch;
|
||||
}
|
||||
}
|
||||
|
||||
internal static HorizontalAlignment ToNativeHorizontalAlignment(this LayoutOptions alignment)
|
||||
{
|
||||
switch (alignment.Alignment)
|
||||
{
|
||||
case LayoutAlignment.Start:
|
||||
return HorizontalAlignment.Left;
|
||||
case LayoutAlignment.Center:
|
||||
return HorizontalAlignment.Center;
|
||||
case LayoutAlignment.End:
|
||||
return HorizontalAlignment.Right;
|
||||
case LayoutAlignment.Fill:
|
||||
return HorizontalAlignment.Stretch;
|
||||
default:
|
||||
return HorizontalAlignment.Stretch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
public static Brush ToBrush(this Color color)
|
||||
{
|
||||
return new SolidColorBrush(color.ToMediaColor());
|
||||
}
|
||||
|
||||
public static System.Windows.Media.Color ToMediaColor(this Color color)
|
||||
{
|
||||
return System.Windows.Media.Color.FromArgb((byte)(color.A * 255), (byte)(color.R * 255), (byte)(color.G * 255), (byte)(color.B * 255));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal static class DeviceExtensions
|
||||
{
|
||||
public static DeviceOrientation ToDeviceOrientation(this System.Windows.Window page)
|
||||
{
|
||||
return page.Height > page.Width ? DeviceOrientation.Portrait : DeviceOrientation.Landscape;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public static class FontExtensions
|
||||
{
|
||||
public static void ApplyFont(this Control self, Font font)
|
||||
{
|
||||
if (font.UseNamedSize)
|
||||
{
|
||||
switch (font.NamedSize)
|
||||
{
|
||||
case NamedSize.Micro:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeSmall"] - 3;
|
||||
break;
|
||||
case NamedSize.Small:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeSmall"];
|
||||
break;
|
||||
case NamedSize.Medium:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeMedium"];
|
||||
// use medium instead of normal as this is the default for non-labels
|
||||
break;
|
||||
case NamedSize.Large:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeLarge"];
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
else
|
||||
self.FontSize = font.FontSize;
|
||||
|
||||
if (!string.IsNullOrEmpty(font.FontFamily))
|
||||
self.FontFamily = new FontFamily(font.FontFamily);
|
||||
else
|
||||
self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["FontFamilySemiBold"];
|
||||
|
||||
if (font.FontAttributes.HasFlag(FontAttributes.Italic))
|
||||
self.FontStyle = FontStyles.Italic;
|
||||
else
|
||||
self.FontStyle = FontStyles.Normal;
|
||||
|
||||
if (font.FontAttributes.HasFlag(FontAttributes.Bold))
|
||||
self.FontWeight = FontWeights.Bold;
|
||||
else
|
||||
self.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
public static void ApplyFont(this TextBlock self, Font font)
|
||||
{
|
||||
if (font.UseNamedSize)
|
||||
{
|
||||
switch (font.NamedSize)
|
||||
{
|
||||
case NamedSize.Micro:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeSmall"] - 3;
|
||||
break;
|
||||
case NamedSize.Small:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeSmall"];
|
||||
break;
|
||||
case NamedSize.Medium:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeNormal"];
|
||||
// use normal instead of medium as this is the default
|
||||
break;
|
||||
case NamedSize.Large:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeLarge"];
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
else
|
||||
self.FontSize = font.FontSize;
|
||||
|
||||
if (!string.IsNullOrEmpty(font.FontFamily))
|
||||
self.FontFamily = new FontFamily(font.FontFamily);
|
||||
else
|
||||
{
|
||||
self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["FontFamilyNormal"];
|
||||
}
|
||||
|
||||
if (font.FontAttributes.HasFlag(FontAttributes.Italic))
|
||||
self.FontStyle = FontStyles.Italic;
|
||||
else
|
||||
self.FontStyle = FontStyles.Normal;
|
||||
|
||||
if (font.FontAttributes.HasFlag(FontAttributes.Bold))
|
||||
self.FontWeight = FontWeights.Bold;
|
||||
else
|
||||
self.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
public static void ApplyFont(this TextElement self, Font font)
|
||||
{
|
||||
if (font.UseNamedSize)
|
||||
{
|
||||
switch (font.NamedSize)
|
||||
{
|
||||
case NamedSize.Micro:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeSmall"] - 3;
|
||||
break;
|
||||
case NamedSize.Small:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeSmall"];
|
||||
break;
|
||||
case NamedSize.Medium:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeNormal"];
|
||||
// use normal instead of medium as this is the default
|
||||
break;
|
||||
case NamedSize.Large:
|
||||
self.FontSize = (double)System.Windows.Application.Current.Resources["FontSizeLarge"];
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
else
|
||||
self.FontSize = font.FontSize;
|
||||
|
||||
if (!string.IsNullOrEmpty(font.FontFamily))
|
||||
self.FontFamily = new FontFamily(font.FontFamily);
|
||||
else
|
||||
self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["FontFamilyNormal"];
|
||||
|
||||
if (font.FontAttributes.HasFlag(FontAttributes.Italic))
|
||||
self.FontStyle = FontStyles.Italic;
|
||||
else
|
||||
self.FontStyle = FontStyles.Normal;
|
||||
|
||||
if (font.FontAttributes.HasFlag(FontAttributes.Bold))
|
||||
self.FontWeight = FontWeights.Bold;
|
||||
else
|
||||
self.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
internal static void ApplyFont(this Control self, IFontElement element)
|
||||
{
|
||||
self.FontSize = element.FontSize;
|
||||
|
||||
if (!string.IsNullOrEmpty(element.FontFamily))
|
||||
self.FontFamily = new FontFamily(element.FontFamily);
|
||||
else
|
||||
self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["FontFamilySemiBold"];
|
||||
|
||||
if (element.FontAttributes.HasFlag(FontAttributes.Italic))
|
||||
self.FontStyle = FontStyles.Italic;
|
||||
else
|
||||
self.FontStyle = FontStyles.Normal;
|
||||
|
||||
if (element.FontAttributes.HasFlag(FontAttributes.Bold))
|
||||
self.FontWeight = FontWeights.Bold;
|
||||
else
|
||||
self.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
internal static bool IsDefault(this IFontElement self)
|
||||
{
|
||||
return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && self.FontAttributes == FontAttributes.None;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public static class FormattedStringExtensions
|
||||
{
|
||||
public static IEnumerable<Inline> ToInlines(this FormattedString formattedString)
|
||||
{
|
||||
foreach (Span span in formattedString.Spans)
|
||||
yield return span.ToRun();
|
||||
}
|
||||
|
||||
public static Run ToRun(this Span span)
|
||||
{
|
||||
var run = new Run { Text = span.Text };
|
||||
|
||||
if (span.ForegroundColor != Color.Default)
|
||||
run.Foreground = span.ForegroundColor.ToBrush();
|
||||
|
||||
if (!span.IsDefault())
|
||||
#pragma warning disable 618
|
||||
run.ApplyFont(span.Font);
|
||||
#pragma warning restore 618
|
||||
|
||||
return run;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public static class FrameworkElementExtensions
|
||||
{
|
||||
public static object UpdateDependencyColor(this DependencyObject depo, DependencyProperty dp, Color newColor)
|
||||
{
|
||||
if (!newColor.IsDefault)
|
||||
depo.SetValue(dp, newColor.ToBrush());
|
||||
else
|
||||
depo.ClearValue(dp);
|
||||
|
||||
return depo.GetValue(dp);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal static class ImageExtensions
|
||||
{
|
||||
public static Stretch ToStretch(this Aspect aspect)
|
||||
{
|
||||
switch (aspect)
|
||||
{
|
||||
case Aspect.Fill:
|
||||
return Stretch.Fill;
|
||||
case Aspect.AspectFill:
|
||||
return Stretch.UniformToFill;
|
||||
default:
|
||||
case Aspect.AspectFit:
|
||||
return Stretch.Uniform;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal static class KeyboardExtensions
|
||||
{
|
||||
public static InputScope ToInputScope(this Keyboard self)
|
||||
{
|
||||
var result = new InputScope();
|
||||
var name = new InputScopeName();
|
||||
if (self == Keyboard.Default)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
else if (self == Keyboard.Chat)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
else if (self == Keyboard.Email)
|
||||
name.NameValue = InputScopeNameValue.EmailUserName;
|
||||
else if (self == Keyboard.Numeric)
|
||||
name.NameValue = InputScopeNameValue.Number;
|
||||
else if (self == Keyboard.Telephone)
|
||||
name.NameValue = InputScopeNameValue.TelephoneNumber;
|
||||
else if (self == Keyboard.Text)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
else if (self == Keyboard.Url)
|
||||
name.NameValue = InputScopeNameValue.Url;
|
||||
else if (self is CustomKeyboard)
|
||||
{
|
||||
var custom = (CustomKeyboard)self;
|
||||
bool capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence;
|
||||
bool spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck;
|
||||
bool suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions;
|
||||
|
||||
if (!capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
|
||||
{
|
||||
Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if spellcheck is enabled");
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
}
|
||||
if (!capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
if (capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
|
||||
{
|
||||
Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if auto Capitalization is enabled");
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
}
|
||||
if (capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
if (capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
|
||||
{
|
||||
Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if spellcheck is enabled");
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
}
|
||||
if (capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should never happens
|
||||
name.NameValue = InputScopeNameValue.Default;
|
||||
}
|
||||
result.Names.Add(name);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF.Extensions
|
||||
{
|
||||
public static class PageExtensions
|
||||
{
|
||||
public static FrameworkElement ToFrameworkElement(this Page view)
|
||||
{
|
||||
if (!Forms.IsInitialized)
|
||||
throw new InvalidOperationException("Call Forms.Init() before this");
|
||||
|
||||
if (!(view.RealParent is Application))
|
||||
{
|
||||
Application app = new DefaultApplication
|
||||
{
|
||||
MainPage = view
|
||||
};
|
||||
|
||||
var formsApplicationPage = new FormsApplicationPage();
|
||||
formsApplicationPage.LoadApplication(app);
|
||||
var platform = new Platform(formsApplicationPage);
|
||||
platform.SetPage(view);
|
||||
}
|
||||
|
||||
IVisualElementRenderer renderer = Platform.GetOrCreateRenderer(view);
|
||||
|
||||
if (renderer == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find or create a renderer for {view}");
|
||||
}
|
||||
|
||||
var frameworkElement = renderer.GetNativeElement();
|
||||
|
||||
frameworkElement.Loaded += (sender, args) =>
|
||||
{
|
||||
view.Layout(new Rectangle(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight));
|
||||
};
|
||||
|
||||
return frameworkElement;
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultApplication : Application
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public static class VisualElementExtensions
|
||||
{
|
||||
internal static void Cleanup(this VisualElement self)
|
||||
{
|
||||
if (self == null)
|
||||
throw new ArgumentNullException("self");
|
||||
|
||||
IVisualElementRenderer renderer = Platform.GetRenderer(self);
|
||||
|
||||
foreach (Element element in self.Descendants())
|
||||
{
|
||||
var visual = element as VisualElement;
|
||||
if (visual == null)
|
||||
continue;
|
||||
|
||||
IVisualElementRenderer childRenderer = Platform.GetRenderer(visual);
|
||||
if (childRenderer != null)
|
||||
{
|
||||
childRenderer.Dispose();
|
||||
Platform.SetRenderer(visual, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderer != null)
|
||||
{
|
||||
renderer.Dispose();
|
||||
Platform.SetRenderer(self, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.Platform.WPF;
|
||||
|
||||
namespace Xamarin.Forms
|
||||
{
|
||||
public static class Forms
|
||||
{
|
||||
public static bool IsInitialized { get; private set; }
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (IsInitialized)
|
||||
return;
|
||||
|
||||
string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
|
||||
System.Windows.Application.Current.Resources.MergedDictionaries.Add(new System.Windows.ResourceDictionary
|
||||
{
|
||||
Source = new Uri(string.Format("/{0};component/WPFResources.xaml", assemblyName), UriKind.Relative)
|
||||
});
|
||||
|
||||
var accentColor = (SolidColorBrush)System.Windows.Application.Current.Resources["AccentColor"];
|
||||
Color.SetAccent(Color.FromRgba(accentColor.Color.R, accentColor.Color.G, accentColor.Color.B, accentColor.Color.A));
|
||||
|
||||
Log.Listeners.Add(new DelegateLogListener((c, m) => Console.WriteLine("[{0}] {1}", m, c)));
|
||||
|
||||
Device.SetTargetIdiom(TargetIdiom.Desktop);
|
||||
Device.PlatformServices = new WPFPlatformServices();
|
||||
Device.Info = new WPFDeviceInfo();
|
||||
ExpressionSearch.Default = new WPFExpressionSearch();
|
||||
|
||||
Registrar.RegisterAll(new[] { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) });
|
||||
|
||||
Ticker.SetDefault(new WPFTicker());
|
||||
Device.SetIdiom(TargetIdiom.Desktop);
|
||||
|
||||
IsInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using WpfLightToolkit.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class FormsApplicationPage : LightWindow
|
||||
{
|
||||
protected Application Application { get; private set; }
|
||||
protected Platform Platform { get; private set; }
|
||||
|
||||
public FormsApplicationPage()
|
||||
{
|
||||
System.Windows.Application.Current.Startup += OnLaunching;
|
||||
System.Windows.Application.Current.Exit += OnClosing;
|
||||
|
||||
MessagingCenter.Send(this, WPFDeviceInfo.BWPorientationChangedName, this.ToDeviceOrientation());
|
||||
SizeChanged += OnOrientationChanged;
|
||||
|
||||
this.ContentLoader = new FormsContentLoader();
|
||||
}
|
||||
|
||||
public void LoadApplication(Application application)
|
||||
{
|
||||
Application.Current = application;
|
||||
application.PropertyChanged += ApplicationOnPropertyChanged;
|
||||
Application = application;
|
||||
|
||||
// Hack around the fact that OnLaunching will haev already happened by this point, sad but needed.
|
||||
application.SendStart();
|
||||
}
|
||||
|
||||
void ApplicationOnPropertyChanged(object sender, PropertyChangedEventArgs args)
|
||||
{
|
||||
if (args.PropertyName == "MainPage")
|
||||
SetMainPage();
|
||||
}
|
||||
|
||||
void OnActivated(object sender, System.EventArgs e)
|
||||
{
|
||||
// TODO : figure out consistency of get this to fire
|
||||
// Check whether tombstoned (terminated, but OS retains information about navigation state and state dictionarys) or dormant
|
||||
Application.SendResume();
|
||||
}
|
||||
|
||||
// when app gets tombstoned, user press back past first page
|
||||
async void OnClosing(object sender, ExitEventArgs e)
|
||||
{
|
||||
// populate isolated storage.
|
||||
//SerializePropertyStore ();
|
||||
await Application.SendSleepAsync();
|
||||
}
|
||||
|
||||
async void OnDeactivated(object sender, System.EventArgs e)
|
||||
{
|
||||
await Application.SendSleepAsync();
|
||||
}
|
||||
|
||||
void OnLaunching(object sender, StartupEventArgs e)
|
||||
{
|
||||
Application.SendStart();
|
||||
}
|
||||
|
||||
void OnOrientationChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
MessagingCenter.Send(this, WPFDeviceInfo.BWPorientationChangedName, this.ToDeviceOrientation());
|
||||
}
|
||||
|
||||
void SetMainPage()
|
||||
{
|
||||
if (Platform == null)
|
||||
Platform = new Platform(this);
|
||||
|
||||
Platform.SetPage(Application.MainPage);
|
||||
}
|
||||
|
||||
protected override void Appearing()
|
||||
{
|
||||
base.Appearing();
|
||||
SetMainPage();
|
||||
}
|
||||
|
||||
public override void OnBackSystemButtonPressed()
|
||||
{
|
||||
Application.NavigationProxy.PopModalAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WpfLightToolkit.Interfaces;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class FormsContentLoader : IContentLoader
|
||||
{
|
||||
public Task<object> LoadContentAsync(FrameworkElement parent, object oldContent, object newContent, CancellationToken cancellationToken)
|
||||
{
|
||||
VisualElement element = oldContent as VisualElement;
|
||||
if (element != null)
|
||||
{
|
||||
element.Cleanup(); // Cleanup old content
|
||||
}
|
||||
|
||||
if (!System.Windows.Application.Current.Dispatcher.CheckAccess())
|
||||
throw new InvalidOperationException("UIThreadRequired");
|
||||
|
||||
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
return Task.Factory.StartNew(() => LoadContent(parent, newContent), cancellationToken, TaskCreationOptions.None, scheduler);
|
||||
}
|
||||
|
||||
protected virtual object LoadContent(FrameworkElement parent, object page)
|
||||
{
|
||||
VisualElement visualElement = page as VisualElement;
|
||||
if (visualElement != null)
|
||||
{
|
||||
var renderer = CreateOrResizeContent(parent, visualElement);
|
||||
return renderer;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnSizeContentChanged(FrameworkElement parent, object page)
|
||||
{
|
||||
VisualElement visualElement = page as VisualElement;
|
||||
if (visualElement != null)
|
||||
{
|
||||
CreateOrResizeContent(parent, visualElement);
|
||||
}
|
||||
}
|
||||
|
||||
private object CreateOrResizeContent(FrameworkElement parent, VisualElement visualElement)
|
||||
{
|
||||
var renderer = Platform.GetOrCreateRenderer(visualElement);
|
||||
|
||||
//if (Debugger.IsAttached)
|
||||
// Console.WriteLine("Page type : " + visualElement.GetType() + " (" + (visualElement as Page).Title + ") -- Parent type : " + visualElement.Parent.GetType() + " -- " + parent.ActualHeight + "H*" + parent.ActualWidth + "W");
|
||||
|
||||
visualElement.Layout(new Rectangle(0, 0, parent.ActualWidth, parent.ActualHeight));
|
||||
|
||||
IPageController pageController = visualElement.RealParent as IPageController;
|
||||
if (pageController != null)
|
||||
pageController.ContainerArea = new Rectangle(0, 0, parent.ActualWidth, parent.ActualHeight);
|
||||
|
||||
return renderer.GetNativeElement();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class FormsPanel : Panel
|
||||
{
|
||||
IElementController ElementController => Element as IElementController;
|
||||
|
||||
public Layout Element { get; private set; }
|
||||
|
||||
public FormsPanel(Layout element)
|
||||
{
|
||||
Element = element;
|
||||
}
|
||||
|
||||
protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
|
||||
{
|
||||
if (Element == null)
|
||||
return finalSize;
|
||||
|
||||
Element.IsInNativeLayout = true;
|
||||
|
||||
for (var i = 0; i < ElementController.LogicalChildren.Count; i++)
|
||||
{
|
||||
var child = ElementController.LogicalChildren[i] as VisualElement;
|
||||
if (child == null)
|
||||
continue;
|
||||
|
||||
IVisualElementRenderer renderer = Platform.GetRenderer(child);
|
||||
if (renderer == null)
|
||||
continue;
|
||||
Rectangle bounds = child.Bounds;
|
||||
|
||||
renderer.GetNativeElement().Arrange(new Rect(bounds.X, bounds.Y, Math.Max(0, bounds.Width), Math.Max(0, bounds.Height)));
|
||||
}
|
||||
|
||||
Element.IsInNativeLayout = false;
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
|
||||
{
|
||||
if (Element == null || availableSize.Width * availableSize.Height == 0)
|
||||
return new System.Windows.Size(0, 0);
|
||||
|
||||
Element.IsInNativeLayout = true;
|
||||
|
||||
for (var i = 0; i < ElementController.LogicalChildren.Count; i++)
|
||||
{
|
||||
var child = ElementController.LogicalChildren[i] as VisualElement;
|
||||
if (child == null)
|
||||
continue;
|
||||
IVisualElementRenderer renderer = Platform.GetRenderer(child);
|
||||
if (renderer == null)
|
||||
continue;
|
||||
|
||||
FrameworkElement control = renderer.GetNativeElement();
|
||||
|
||||
if (control.ActualWidth != child.Width || control.ActualHeight != child.Height)
|
||||
{
|
||||
double width = child.Width <= -1 ? ActualWidth : child.Width;
|
||||
double height = child.Height <= -1 ? ActualHeight : child.Height;
|
||||
control.Measure(new System.Windows.Size(width, height));
|
||||
}
|
||||
}
|
||||
|
||||
System.Windows.Size result;
|
||||
if (double.IsInfinity(availableSize.Width) || double.IsPositiveInfinity(availableSize.Height))
|
||||
{
|
||||
Size request = Element.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request;
|
||||
result = new System.Windows.Size(request.Width, request.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = availableSize;
|
||||
}
|
||||
Element.IsInNativeLayout = false;
|
||||
|
||||
if (Double.IsPositiveInfinity(result.Height))
|
||||
result.Height = 0.0;
|
||||
if (Double.IsPositiveInfinity(result.Width))
|
||||
result.Width = 0.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// An intermediate class for injecting bindings for things the default
|
||||
/// textbox doesn't allow us to bind/modify
|
||||
/// </summary>
|
||||
public class FormsTextBox : TextBox
|
||||
{
|
||||
const char ObfuscationCharacter = '●';
|
||||
|
||||
public static readonly DependencyProperty PlaceholderForegroundBrushProperty = DependencyProperty.Register("PlaceholderForegroundBrush", typeof(Brush), typeof(FormsTextBox),
|
||||
new PropertyMetadata(default(Brush)));
|
||||
|
||||
public static readonly DependencyProperty IsPasswordProperty = DependencyProperty.Register("IsPassword", typeof(bool), typeof(FormsTextBox),
|
||||
new PropertyMetadata(default(bool), OnIsPasswordChanged));
|
||||
|
||||
public new static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FormsTextBox), new PropertyMetadata("", TextPropertyChanged));
|
||||
|
||||
protected internal static readonly DependencyProperty DisabledTextProperty = DependencyProperty.Register("DisabledText", typeof(string), typeof(FormsTextBox), new PropertyMetadata(""));
|
||||
|
||||
static InputScope s_passwordInputScope;
|
||||
InputScope _cachedInputScope;
|
||||
CancellationTokenSource _cts;
|
||||
bool _internalChangeFlag;
|
||||
|
||||
public FormsTextBox()
|
||||
{
|
||||
TextChanged += OnTextChanged;
|
||||
SelectionChanged += OnSelectionChanged;
|
||||
}
|
||||
|
||||
public bool IsPassword
|
||||
{
|
||||
get { return (bool)GetValue(IsPasswordProperty); }
|
||||
set { SetValue(IsPasswordProperty, value); }
|
||||
}
|
||||
|
||||
public Brush PlaceholderForegroundBrush
|
||||
{
|
||||
get { return (Brush)GetValue(PlaceholderForegroundBrushProperty); }
|
||||
set { SetValue(PlaceholderForegroundBrushProperty, value); }
|
||||
}
|
||||
|
||||
public new string Text
|
||||
{
|
||||
get { return (string)GetValue(TextProperty); }
|
||||
set { SetValue(TextProperty, value); }
|
||||
}
|
||||
|
||||
protected internal string DisabledText
|
||||
{
|
||||
get { return (string)GetValue(DisabledTextProperty); }
|
||||
set { SetValue(DisabledTextProperty, value); }
|
||||
}
|
||||
|
||||
static InputScope PasswordInputScope
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_passwordInputScope != null)
|
||||
return s_passwordInputScope;
|
||||
|
||||
s_passwordInputScope = new InputScope();
|
||||
var name = new InputScopeName { NameValue = InputScopeNameValue.Default };
|
||||
s_passwordInputScope.Names.Add(name);
|
||||
|
||||
return s_passwordInputScope;
|
||||
}
|
||||
}
|
||||
|
||||
void DelayObfuscation()
|
||||
{
|
||||
int lengthDifference = base.Text.Length - Text.Length;
|
||||
|
||||
string updatedRealText = DetermineTextFromPassword(Text, base.Text);
|
||||
|
||||
if (Text == updatedRealText)
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
Text = updatedRealText;
|
||||
|
||||
// Cancel any pending delayed obfuscation
|
||||
_cts?.Cancel();
|
||||
_cts = null;
|
||||
|
||||
string newText;
|
||||
|
||||
if (lengthDifference != 1)
|
||||
{
|
||||
// Either More than one character got added in this text change (e.g., a paste operation)
|
||||
// Or characters were removed. Either way, we don't need to do the delayed obfuscation dance
|
||||
newText = Obfuscate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only one character was added; we need to leave it visible for a brief time period
|
||||
// Obfuscate all but the last character for now
|
||||
newText = Obfuscate(true);
|
||||
|
||||
// Leave the last character visible until a new character is added
|
||||
// or sufficient time has passed
|
||||
if (_cts == null)
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(0.5), _cts.Token);
|
||||
_cts.Token.ThrowIfCancellationRequested();
|
||||
await Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
base.Text = Obfuscate();
|
||||
SelectionStart = base.Text.Length;
|
||||
}));
|
||||
}, _cts.Token);
|
||||
}
|
||||
|
||||
if (base.Text == newText)
|
||||
return;
|
||||
|
||||
base.Text = newText;
|
||||
SelectionStart = base.Text.Length;
|
||||
}
|
||||
|
||||
static string DetermineTextFromPassword(string realText, string passwordText)
|
||||
{
|
||||
int firstObfuscationChar = passwordText.IndexOf(ObfuscationCharacter);
|
||||
|
||||
if (firstObfuscationChar > 0)
|
||||
{
|
||||
// The user is typing faster than we can process, and the text is coming in at the beginning
|
||||
// of the textbox instead of the end
|
||||
passwordText = passwordText.Substring(firstObfuscationChar, passwordText.Length - firstObfuscationChar) + passwordText.Substring(0, firstObfuscationChar);
|
||||
}
|
||||
|
||||
if (realText.Length == passwordText.Length)
|
||||
return realText;
|
||||
|
||||
if (passwordText.Length == 0)
|
||||
return "";
|
||||
|
||||
if (passwordText.Length < realText.Length)
|
||||
return realText.Substring(0, passwordText.Length);
|
||||
|
||||
int lengthDifference = passwordText.Length - realText.Length;
|
||||
|
||||
return realText + passwordText.Substring(passwordText.Length - lengthDifference, lengthDifference);
|
||||
}
|
||||
|
||||
string Obfuscate(bool leaveLastVisible = false)
|
||||
{
|
||||
if (leaveLastVisible && Text.Length == 1)
|
||||
return Text;
|
||||
|
||||
if (leaveLastVisible && Text.Length > 1)
|
||||
return new string(ObfuscationCharacter, Text.Length - 1) + Text.Substring(Text.Length - 1, 1);
|
||||
|
||||
return new string(ObfuscationCharacter, Text.Length);
|
||||
}
|
||||
|
||||
static void OnIsPasswordChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
var textBox = (FormsTextBox)dependencyObject;
|
||||
textBox.UpdateInputScope();
|
||||
textBox.SyncBaseText();
|
||||
}
|
||||
|
||||
void OnSelectionChanged(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
if (!IsPassword)
|
||||
return;
|
||||
|
||||
// Prevent the user from selecting any text in the password box by forcing all selection
|
||||
// to zero-length at the end of the text
|
||||
// This simulates the "do not allow clipboard copy" behavior the PasswordBox control has
|
||||
if (SelectionLength > 0 || SelectionStart < Text.Length)
|
||||
{
|
||||
if (SelectionLength != 0)
|
||||
SelectionLength = 0;
|
||||
SelectionStart = Text.Length;
|
||||
}
|
||||
}
|
||||
|
||||
void OnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
|
||||
{
|
||||
if (IsPassword)
|
||||
DelayObfuscation();
|
||||
else if (base.Text != Text)
|
||||
{
|
||||
// Not in password mode, so we just need to make the "real" Text match
|
||||
// what's in the textbox; the internalChange flag keeps the TextProperty
|
||||
// synchronization from happening
|
||||
_internalChangeFlag = true;
|
||||
Text = base.Text;
|
||||
_internalChangeFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SyncBaseText()
|
||||
{
|
||||
if (_internalChangeFlag)
|
||||
return;
|
||||
|
||||
base.Text = IsPassword ? Obfuscate() : Text;
|
||||
DisabledText = base.Text;
|
||||
|
||||
SelectionStart = base.Text.Length;
|
||||
}
|
||||
|
||||
static void TextPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
var textBox = (FormsTextBox)dependencyObject;
|
||||
textBox.SyncBaseText();
|
||||
}
|
||||
|
||||
void UpdateInputScope()
|
||||
{
|
||||
if (IsPassword)
|
||||
{
|
||||
_cachedInputScope = InputScope;
|
||||
InputScope = PasswordInputScope; // We don't want suggestions turned on if we're in password mode
|
||||
}
|
||||
else
|
||||
InputScope = _cachedInputScope;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF.Helpers
|
||||
{
|
||||
static class UiHelper
|
||||
{
|
||||
public static void ExecuteInUiThread(Action action)
|
||||
{
|
||||
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public interface ICellRenderer : IRegisterable
|
||||
{
|
||||
System.Windows.DataTemplate GetTemplate(Cell cell);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public interface IVisualElementRenderer : IRegisterable, IDisposable
|
||||
{
|
||||
FrameworkElement GetNativeElement();
|
||||
|
||||
VisualElement Element { get; }
|
||||
|
||||
event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
||||
|
||||
SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint);
|
||||
|
||||
void SetElement(VisualElement element);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
|
@ -0,0 +1,252 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WpfLightToolkit.Controls;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class Platform : BindableObject, IPlatform, INavigation
|
||||
{
|
||||
readonly FormsApplicationPage _page;
|
||||
Page Page { get; set; }
|
||||
|
||||
internal static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(IVisualElementRenderer), typeof(Platform), default(IVisualElementRenderer));
|
||||
|
||||
internal Platform(FormsApplicationPage page)
|
||||
{
|
||||
_page = page;
|
||||
|
||||
|
||||
var busyCount = 0;
|
||||
MessagingCenter.Subscribe(this, Page.BusySetSignalName, (Page sender, bool enabled) =>
|
||||
{
|
||||
busyCount = Math.Max(0, enabled ? busyCount + 1 : busyCount - 1);
|
||||
});
|
||||
|
||||
MessagingCenter.Subscribe<Page, AlertArguments>(this, Page.AlertSignalName, OnPageAlert);
|
||||
MessagingCenter.Subscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName, OnPageActionSheet);
|
||||
|
||||
}
|
||||
|
||||
async void OnPageAlert(Page sender, AlertArguments options)
|
||||
{
|
||||
string content = options.Message ?? options.Title ?? string.Empty;
|
||||
|
||||
LightContentDialog dialog = new LightContentDialog();
|
||||
|
||||
if (options.Message == null || options.Title == null)
|
||||
dialog.Content = content;
|
||||
else
|
||||
{
|
||||
dialog.Title = options.Title;
|
||||
dialog.Content = options.Message;
|
||||
}
|
||||
|
||||
if (options.Accept != null)
|
||||
{
|
||||
dialog.IsPrimaryButtonEnabled = true;
|
||||
dialog.PrimaryButtonText = options.Accept;
|
||||
}
|
||||
|
||||
if (options.Cancel != null)
|
||||
{
|
||||
dialog.IsSecondaryButtonEnabled = true;
|
||||
dialog.SecondaryButtonText = options.Cancel;
|
||||
}
|
||||
|
||||
var dialogResult = await dialog.ShowAsync();
|
||||
|
||||
options.SetResult(dialogResult == LightContentDialogResult.Primary);
|
||||
}
|
||||
|
||||
|
||||
async void OnPageActionSheet(Page sender, ActionSheetArguments options)
|
||||
{
|
||||
var list = new System.Windows.Controls.ListView
|
||||
{
|
||||
Style = (System.Windows.Style)System.Windows.Application.Current.Resources["ActionSheetList"],
|
||||
ItemsSource = options.Buttons
|
||||
};
|
||||
|
||||
var dialog = new LightContentDialog
|
||||
{
|
||||
Content = list,
|
||||
};
|
||||
|
||||
if (options.Title != null)
|
||||
dialog.Title = options.Title;
|
||||
|
||||
list.SelectionChanged += (s, e) =>
|
||||
{
|
||||
if(list.SelectedItem != null)
|
||||
{
|
||||
dialog.Hide();
|
||||
options.SetResult((string)list.SelectedItem);
|
||||
}
|
||||
};
|
||||
|
||||
/*_page.KeyDown += (window, e) =>
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Escape)
|
||||
{
|
||||
dialog.Hide();
|
||||
options.SetResult(LightContentDialogResult.None.ToString());
|
||||
}
|
||||
};*/
|
||||
|
||||
if (options.Cancel != null)
|
||||
{
|
||||
dialog.IsSecondaryButtonEnabled = true;
|
||||
dialog.SecondaryButtonText = options.Cancel;
|
||||
}
|
||||
|
||||
if (options.Destruction != null)
|
||||
{
|
||||
dialog.IsPrimaryButtonEnabled = true;
|
||||
dialog.PrimaryButtonText = options.Destruction;
|
||||
}
|
||||
|
||||
LightContentDialogResult result = await dialog.ShowAsync();
|
||||
if (result == LightContentDialogResult.Secondary)
|
||||
options.SetResult(options.Cancel);
|
||||
else if (result == LightContentDialogResult.Primary)
|
||||
options.SetResult(options.Destruction);
|
||||
|
||||
}
|
||||
|
||||
public SizeRequest GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if (widthConstraint > 0 && heightConstraint > 0 && GetRenderer(view) != null)
|
||||
{
|
||||
IVisualElementRenderer element = GetRenderer(view);
|
||||
return element.GetDesiredSize(widthConstraint, heightConstraint);
|
||||
}
|
||||
|
||||
return new SizeRequest();
|
||||
}
|
||||
|
||||
public static IVisualElementRenderer GetOrCreateRenderer(VisualElement element)
|
||||
{
|
||||
if (GetRenderer(element) == null)
|
||||
SetRenderer(element, CreateRenderer(element));
|
||||
|
||||
return GetRenderer(element);
|
||||
}
|
||||
|
||||
public static IVisualElementRenderer CreateRenderer(VisualElement element)
|
||||
{
|
||||
IVisualElementRenderer result = Registrar.Registered.GetHandler<IVisualElementRenderer>(element.GetType()) ?? new DefaultViewRenderer();
|
||||
result.SetElement(element);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IVisualElementRenderer GetRenderer(VisualElement self)
|
||||
{
|
||||
return (IVisualElementRenderer)self.GetValue(RendererProperty);
|
||||
}
|
||||
|
||||
public static void SetRenderer(VisualElement self, IVisualElementRenderer renderer)
|
||||
{
|
||||
self.SetValue(RendererProperty, renderer);
|
||||
self.IsPlatformEnabled = renderer != null;
|
||||
}
|
||||
|
||||
internal void SetPage(Page newRoot)
|
||||
{
|
||||
if (newRoot == null)
|
||||
return;
|
||||
|
||||
Page = newRoot;
|
||||
Page.Platform = this;
|
||||
_page.StartupPage = Page;
|
||||
Application.Current.NavigationProxy.Inner = this;
|
||||
}
|
||||
|
||||
|
||||
public IReadOnlyList<Page> NavigationStack
|
||||
{
|
||||
get { throw new InvalidOperationException("NavigationStack is not supported globally on Windows, please use a NavigationPage."); }
|
||||
}
|
||||
|
||||
public IReadOnlyList<Page> ModalStack
|
||||
{
|
||||
get
|
||||
{
|
||||
return _page.InternalChildren.Cast<Page>().ToList(); }
|
||||
}
|
||||
|
||||
Task INavigation.PushAsync(Page root)
|
||||
{
|
||||
return ((INavigation)this).PushAsync(root, true);
|
||||
}
|
||||
|
||||
Task<Page> INavigation.PopAsync()
|
||||
{
|
||||
return ((INavigation)this).PopAsync(true);
|
||||
}
|
||||
|
||||
Task INavigation.PopToRootAsync()
|
||||
{
|
||||
return ((INavigation)this).PopToRootAsync(true);
|
||||
}
|
||||
|
||||
Task INavigation.PushAsync(Page root, bool animated)
|
||||
{
|
||||
throw new InvalidOperationException("PushAsync is not supported globally on Windows, please use a NavigationPage.");
|
||||
}
|
||||
|
||||
Task<Page> INavigation.PopAsync(bool animated)
|
||||
{
|
||||
throw new InvalidOperationException("PopAsync is not supported globally on Windows, please use a NavigationPage.");
|
||||
}
|
||||
|
||||
Task INavigation.PopToRootAsync(bool animated)
|
||||
{
|
||||
throw new InvalidOperationException("PopToRootAsync is not supported globally on Windows, please use a NavigationPage.");
|
||||
}
|
||||
|
||||
void INavigation.RemovePage(Page page)
|
||||
{
|
||||
throw new InvalidOperationException("RemovePage is not supported globally on Windows, please use a NavigationPage.");
|
||||
}
|
||||
|
||||
void INavigation.InsertPageBefore(Page page, Page before)
|
||||
{
|
||||
throw new InvalidOperationException("InsertPageBefore is not supported globally on Windows, please use a NavigationPage.");
|
||||
}
|
||||
|
||||
Task INavigation.PushModalAsync(Page page)
|
||||
{
|
||||
return ((INavigation)this).PushModalAsync(page, true);
|
||||
}
|
||||
|
||||
Task<Page> INavigation.PopModalAsync()
|
||||
{
|
||||
return ((INavigation)this).PopModalAsync(true);
|
||||
}
|
||||
|
||||
Task INavigation.PushModalAsync(Page page, bool animated)
|
||||
{
|
||||
if (page == null)
|
||||
throw new ArgumentNullException(nameof(page));
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
page.Platform = this;
|
||||
_page.PushModal(page, animated);
|
||||
tcs.SetResult(true);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
Task<Page> INavigation.PopModalAsync(bool animated)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<Page>();
|
||||
var page =_page.PopModal(animated) as Page;
|
||||
tcs.SetResult(page);
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public abstract class PlatformEffect : PlatformEffect<FrameworkElement, FrameworkElement>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Platform.WPF;
|
||||
|
||||
// Les informations générales relatives à un assembly dépendent de
|
||||
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
|
||||
// associées à un assembly.
|
||||
[assembly: AssemblyTitle("Xamarin.Forms.Platform.WPF")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Xamarin.Forms.Platform.WPF")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
|
||||
// aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
|
||||
// COM, affectez la valeur true à l'attribut ComVisible sur ce type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//Pour commencer à générer des applications localisables, définissez
|
||||
//<UICulture>CultureUtiliséePourCoder</UICulture> dans votre fichier .csproj
|
||||
//dans <PropertyGroup>. Par exemple, si vous utilisez le français
|
||||
//dans vos fichiers sources, définissez <UICulture> à fr-FR. Puis, supprimez les marques de commentaire de
|
||||
//l'attribut NeutralResourceLanguage ci-dessous. Mettez à jour "fr-FR" dans
|
||||
//la ligne ci-après pour qu'elle corresponde au paramètre UICulture du fichier projet.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //où se trouvent les dictionnaires de ressources spécifiques à un thème
|
||||
//(utilisé si une ressource est introuvable dans la page,
|
||||
// ou dictionnaires de ressources de l'application)
|
||||
ResourceDictionaryLocation.SourceAssembly //où se trouve le dictionnaire de ressources générique
|
||||
//(utilisé si une ressource est introuvable dans la page,
|
||||
// dans l'application ou dans l'un des dictionnaires de ressources spécifiques à un thème)
|
||||
)]
|
||||
|
||||
|
||||
// Les informations de version pour un assembly se composent des quatre valeurs suivantes :
|
||||
//
|
||||
// Version principale
|
||||
// Version secondaire
|
||||
// Numéro de build
|
||||
// Révision
|
||||
//
|
||||
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
|
||||
// en utilisant '*', comme indiqué ci-dessous :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
||||
[assembly: ExportRenderer(typeof(Layout), typeof(LayoutRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
|
||||
[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
|
||||
[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
|
||||
[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Image), typeof(ImageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
|
||||
[assembly: ExportRenderer(typeof(WebView), typeof(WebViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(SearchBar), typeof(SearchBarRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
|
||||
[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Picker), typeof(PickerRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Stepper), typeof(StepperRenderer))]
|
||||
[assembly: ExportRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer))]
|
||||
[assembly: ExportRenderer(typeof(ScrollView), typeof(ScrollViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
|
||||
[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(OpenGLView), typeof(OpenGLViewRenderer))]
|
||||
|
||||
// Control don't exist natively in WPF Platform
|
||||
[assembly: ExportRenderer(typeof(TableView), typeof(TableViewRenderer))]
|
||||
//**[assembly: ExportRenderer(typeof(NavigationMenu), typeof(NavigationMenuRenderer))]
|
||||
//**[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePickerRenderer))]
|
||||
//**[assembly: ExportRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer))]
|
||||
|
||||
//ImageSources
|
||||
|
||||
[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
|
||||
[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImageSourceHandler))]
|
||||
[assembly: ExportImageSourceHandler(typeof(UriImageSource), typeof(UriImageSourceHandler))]
|
||||
|
||||
|
||||
// Form and subclasses
|
||||
[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedPageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MasterDetailPageRenderer))]
|
||||
|
||||
// Cells
|
||||
[assembly: ExportCell(typeof(Cell), typeof(TextCellRenderer))]
|
||||
[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
|
||||
[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
|
||||
[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
|
||||
[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))]
|
||||
|
||||
// Others
|
||||
[assembly: Xamarin.Forms.Dependency(typeof(ResourcesProvider))]
|
|
@ -0,0 +1,63 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Ce code a été généré par un outil.
|
||||
// Version du runtime :4.0.30319.42000
|
||||
//
|
||||
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
|
||||
// le code est régénéré.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
|
||||
/// </summary>
|
||||
// Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
|
||||
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
|
||||
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
|
||||
// avec l'option /str ou régénérez votre projet VS.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xamarin.Forms.Platform.WPF.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remplace la propriété CurrentUICulture du thread actuel pour toutes
|
||||
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -0,0 +1,26 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Ce code a été généré par un outil.
|
||||
// Version du runtime :4.0.30319.42000
|
||||
//
|
||||
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
|
||||
// le code est régénéré.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WProgressBar = System.Windows.Controls.ProgressBar;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class ActivityIndicatorRenderer : ViewRenderer<ActivityIndicator, WProgressBar>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<ActivityIndicator> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WProgressBar());
|
||||
}
|
||||
|
||||
UpdateIsIndeterminate();
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == ActivityIndicator.IsRunningProperty.PropertyName)
|
||||
UpdateIsIndeterminate();
|
||||
else if (e.PropertyName == ActivityIndicator.ColorProperty.PropertyName)
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
void UpdateColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(WProgressBar.ForegroundProperty, Element.Color);
|
||||
}
|
||||
|
||||
void UpdateIsIndeterminate()
|
||||
{
|
||||
Control.IsIndeterminate = Element.IsRunning;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WRectangle = System.Windows.Shapes.Rectangle;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class BoxViewRenderer : ViewRenderer<BoxView, WRectangle>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WRectangle());
|
||||
}
|
||||
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == BoxView.ColorProperty.PropertyName)
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
void UpdateColor()
|
||||
{
|
||||
Color color = Element.Color != Color.Default ? Element.Color : Element.BackgroundColor;
|
||||
Control.UpdateDependencyColor(WRectangle.FillProperty, color);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using WButton = System.Windows.Controls.Button;
|
||||
using WImage = System.Windows.Controls.Image;
|
||||
using WThickness = System.Windows.Thickness;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class ButtonRenderer : ViewRenderer<Button, WButton>
|
||||
{
|
||||
bool _fontApplied;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WButton());
|
||||
Control.Click += HandleButtonClick;
|
||||
}
|
||||
|
||||
UpdateContent();
|
||||
|
||||
if (Element.TextColor != Color.Default)
|
||||
UpdateTextColor();
|
||||
|
||||
if (Element.BorderColor != Color.Default)
|
||||
UpdateBorderColor();
|
||||
|
||||
if (Element.BorderWidth != 0)
|
||||
UpdateBorderWidth();
|
||||
|
||||
UpdateFont();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Button.TextProperty.PropertyName || e.PropertyName == Button.ImageProperty.PropertyName)
|
||||
UpdateContent();
|
||||
else if (e.PropertyName == Button.TextColorProperty.PropertyName)
|
||||
UpdateTextColor();
|
||||
else if (e.PropertyName == Button.FontProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Button.BorderColorProperty.PropertyName)
|
||||
UpdateBorderColor();
|
||||
else if (e.PropertyName == Button.BorderWidthProperty.PropertyName)
|
||||
UpdateBorderWidth();
|
||||
}
|
||||
|
||||
void HandleButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IButtonController buttonView = Element as IButtonController;
|
||||
if (buttonView != null)
|
||||
buttonView.SendClicked();
|
||||
}
|
||||
|
||||
void UpdateBorderColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(WButton.BorderBrushProperty, Element.BorderColor);
|
||||
}
|
||||
|
||||
void UpdateBorderWidth()
|
||||
{
|
||||
Control.BorderThickness = Element.BorderWidth <= 0d ? new WThickness(1) : new WThickness(Element.BorderWidth);
|
||||
}
|
||||
|
||||
void UpdateContent()
|
||||
{
|
||||
var text = Element.Text;
|
||||
var elementImage = Element.Image;
|
||||
|
||||
// No image, just the text
|
||||
if (elementImage == null)
|
||||
{
|
||||
Control.Content = text;
|
||||
return;
|
||||
}
|
||||
|
||||
var image = new WImage
|
||||
{
|
||||
Source = new BitmapImage(new Uri("/" + elementImage.File, UriKind.Relative)),
|
||||
Width = 30,
|
||||
Height = 30,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
HorizontalAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
|
||||
// No text, just the image
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
Control.Content = image;
|
||||
return;
|
||||
}
|
||||
|
||||
// Both image and text, so we need to build a container for them
|
||||
var layout = Element.ContentLayout;
|
||||
var container = new StackPanel();
|
||||
var textBlock = new TextBlock
|
||||
{
|
||||
Text = text,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
HorizontalAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
|
||||
var spacing = layout.Spacing;
|
||||
|
||||
container.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
container.VerticalAlignment = VerticalAlignment.Center;
|
||||
|
||||
switch (layout.Position)
|
||||
{
|
||||
case Button.ButtonContentLayout.ImagePosition.Top:
|
||||
container.Orientation = Orientation.Vertical;
|
||||
image.Margin = new WThickness(0, 0, 0, spacing);
|
||||
break;
|
||||
case Button.ButtonContentLayout.ImagePosition.Bottom:
|
||||
container.Orientation = Orientation.Vertical;
|
||||
image.Margin = new WThickness(0, spacing, 0, 0);
|
||||
break;
|
||||
case Button.ButtonContentLayout.ImagePosition.Right:
|
||||
container.Orientation = Orientation.Horizontal;
|
||||
image.Margin = new WThickness(spacing, 0, 0, 0);
|
||||
break;
|
||||
default:
|
||||
// Defaults to image on the left
|
||||
container.Orientation = Orientation.Horizontal;
|
||||
image.Margin = new WThickness(0, 0, spacing, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
container.Children.Add(image);
|
||||
container.Children.Add(textBlock);
|
||||
|
||||
Control.Content = container;
|
||||
}
|
||||
|
||||
void UpdateFont()
|
||||
{
|
||||
if (Control == null || Element == null)
|
||||
return;
|
||||
|
||||
if (Element.Font == Font.Default && !_fontApplied)
|
||||
return;
|
||||
|
||||
Font fontToApply = Element.Font == Font.Default ? Font.SystemFontOfSize(NamedSize.Medium) : Element.Font;
|
||||
|
||||
Control.ApplyFont(fontToApply);
|
||||
_fontApplied = true;
|
||||
}
|
||||
|
||||
void UpdateTextColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(WButton.ForegroundProperty, Element.TextColor);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.Click -= HandleButtonClick;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WpfLightToolkit.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class CarouselPageRenderer : VisualMultiPageRenderer<CarouselPage, ContentPage, LightCarouselPage>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new LightCarouselPage() { ContentLoader = new FormsContentLoader() });
|
||||
}
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Controls;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class TextCellRenderer : ICellRenderer
|
||||
{
|
||||
public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
|
||||
{
|
||||
/*if (cell.RealParent is ListView)
|
||||
{
|
||||
if (cell.GetIsGroupHeader<ItemsView<Cell>, Cell>())
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ListViewHeaderTextCell"];
|
||||
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ListViewTextCell"];
|
||||
}*/
|
||||
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["TextCell"];
|
||||
}
|
||||
}
|
||||
|
||||
public class EntryCellRendererCompleted : ICommand
|
||||
{
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
var entryCell = (IEntryCellController)parameter;
|
||||
entryCell.SendCompleted();
|
||||
}
|
||||
|
||||
protected virtual void OnCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public class EntryCellPhoneTextBox : TextBox
|
||||
{
|
||||
public event EventHandler KeyboardReturnPressed;
|
||||
|
||||
protected override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
EventHandler handler = KeyboardReturnPressed;
|
||||
if (handler != null)
|
||||
handler(this, EventArgs.Empty);
|
||||
}
|
||||
base.OnKeyUp(e);
|
||||
}
|
||||
}
|
||||
|
||||
public class EntryCellRenderer : ICellRenderer
|
||||
{
|
||||
public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
|
||||
{
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["EntryCell"];
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewCellRenderer : ICellRenderer
|
||||
{
|
||||
public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
|
||||
{
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ViewCell"];
|
||||
}
|
||||
}
|
||||
|
||||
public class SwitchCellRenderer : ICellRenderer
|
||||
{
|
||||
public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
|
||||
{
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["SwitchCell"];
|
||||
}
|
||||
}
|
||||
|
||||
public class ImageCellRenderer : ICellRenderer
|
||||
{
|
||||
public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
|
||||
{
|
||||
return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ImageCell"];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WDatePicker = System.Windows.Controls.DatePicker;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class DatePickerRenderer : ViewRenderer<DatePicker, WDatePicker>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WDatePicker());
|
||||
Control.SelectedDateChanged += OnNativeSelectedDateChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateDate();
|
||||
UpdateMinimumDate();
|
||||
UpdateMaximumDate();
|
||||
UpdateTextColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == DatePicker.DateProperty.PropertyName)
|
||||
UpdateDate();
|
||||
else if (e.PropertyName == DatePicker.MaximumDateProperty.PropertyName)
|
||||
UpdateMaximumDate();
|
||||
else if (e.PropertyName == DatePicker.MinimumDateProperty.PropertyName)
|
||||
UpdateMinimumDate();
|
||||
else if (e.PropertyName == DatePicker.TextColorProperty.PropertyName)
|
||||
UpdateTextColor();
|
||||
}
|
||||
|
||||
void UpdateDate()
|
||||
{
|
||||
Control.SelectedDate = Element.Date;
|
||||
}
|
||||
|
||||
void UpdateMaximumDate()
|
||||
{
|
||||
Control.DisplayDateEnd = Element.MaximumDate;
|
||||
}
|
||||
|
||||
void UpdateMinimumDate()
|
||||
{
|
||||
Control.DisplayDateStart = Element.MinimumDate;
|
||||
}
|
||||
|
||||
void UpdateTextColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(WDatePicker.ForegroundProperty, Element.TextColor);
|
||||
}
|
||||
|
||||
void OnNativeSelectedDateChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
if (Control.SelectedDate.HasValue)
|
||||
((IElementController)Element).SetValueFromRenderer(DatePicker.DateProperty, Control.SelectedDate.Value);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.SelectedDateChanged -= OnNativeSelectedDateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class EditorRenderer : ViewRenderer<Editor, TextBox>
|
||||
{
|
||||
bool _fontApplied;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new TextBox { VerticalScrollBarVisibility = ScrollBarVisibility.Visible, TextWrapping = TextWrapping.Wrap, AcceptsReturn = true });
|
||||
Control.LostFocus += NativeOnLostFocus;
|
||||
Control.TextChanged += NativeOnTextChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateText();
|
||||
UpdateInputScope();
|
||||
UpdateTextColor();
|
||||
UpdateFont();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Editor.TextProperty.PropertyName)
|
||||
UpdateText();
|
||||
else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
|
||||
UpdateInputScope();
|
||||
else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
|
||||
UpdateTextColor();
|
||||
else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
|
||||
UpdateFont();
|
||||
}
|
||||
|
||||
void NativeOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(Editor.TextProperty, Control.Text);
|
||||
}
|
||||
|
||||
void NativeOnLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Element.SendCompleted();
|
||||
}
|
||||
|
||||
void UpdateFont()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Editor editor = Element;
|
||||
|
||||
bool editorIsDefault = editor.FontFamily == null && editor.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Editor), true) && editor.FontAttributes == FontAttributes.None;
|
||||
if (editor == null || (editorIsDefault && !_fontApplied))
|
||||
return;
|
||||
|
||||
if (editorIsDefault)
|
||||
{
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontStyleProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontSizeProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontFamilyProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontWeightProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontStretchProperty);
|
||||
}
|
||||
else
|
||||
Control.ApplyFont(editor);
|
||||
|
||||
_fontApplied = true;
|
||||
}
|
||||
|
||||
void UpdateInputScope()
|
||||
{
|
||||
Control.InputScope = Element.Keyboard.ToInputScope();
|
||||
}
|
||||
|
||||
void UpdateText()
|
||||
{
|
||||
string newText = Element.Text ?? "";
|
||||
|
||||
if (Control.Text == newText)
|
||||
return;
|
||||
|
||||
Control.Text = newText;
|
||||
Control.SelectionStart = Control.Text.Length;
|
||||
}
|
||||
|
||||
void UpdateTextColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(System.Windows.Controls.Control.ForegroundProperty, Element.TextColor);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.LostFocus -= NativeOnLostFocus;
|
||||
Control.TextChanged -= NativeOnTextChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
using static System.String;
|
||||
using WControl = System.Windows.Controls.Control;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
|
||||
public class EntryRenderer : ViewRenderer<Entry, FormsTextBox>
|
||||
{
|
||||
bool _fontApplied;
|
||||
bool _ignoreTextChange;
|
||||
Brush _placeholderDefaultBrush;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new FormsTextBox());
|
||||
Control.LostFocus += OnTextBoxUnfocused;
|
||||
Control.TextChanged += TextBoxOnTextChanged;
|
||||
Control.KeyUp += TextBoxOnKeyUp;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateInputScope();
|
||||
UpdateIsPassword();
|
||||
UpdateText();
|
||||
UpdatePlaceholder();
|
||||
UpdateColor();
|
||||
UpdateFont();
|
||||
UpdateAlignment();
|
||||
UpdatePlaceholderColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Entry.TextProperty.PropertyName)
|
||||
UpdateText();
|
||||
else if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
|
||||
UpdatePlaceholder();
|
||||
else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
|
||||
UpdateIsPassword();
|
||||
else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
|
||||
UpdateColor();
|
||||
else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
|
||||
UpdateInputScope();
|
||||
else if (e.PropertyName == Entry.FontAttributesProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Entry.FontFamilyProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Entry.FontSizeProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
|
||||
UpdateAlignment();
|
||||
else if (e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
|
||||
UpdatePlaceholderColor();
|
||||
}
|
||||
|
||||
internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
|
||||
{
|
||||
if (args.Focus)
|
||||
args.Result = Control.Focus();
|
||||
else
|
||||
{
|
||||
UnfocusControl(Control);
|
||||
args.Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OnTextBoxUnfocused(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Element.TextColor.IsDefault)
|
||||
return;
|
||||
|
||||
if (!IsNullOrEmpty(Element.Text))
|
||||
Control.Foreground = Element.TextColor.ToBrush();
|
||||
}
|
||||
|
||||
void TextBoxOnKeyUp(object sender, KeyEventArgs keyEventArgs)
|
||||
{
|
||||
if (keyEventArgs.Key == Key.Enter)
|
||||
((IEntryController)Element).SendCompleted();
|
||||
}
|
||||
|
||||
void TextBoxOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
|
||||
{
|
||||
// Signal to the UpdateText method that the change to TextProperty doesn't need to update the control
|
||||
// This prevents the cursor position from getting lost
|
||||
_ignoreTextChange = true;
|
||||
((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, Control.Text);
|
||||
|
||||
// If an Entry.TextChanged handler modified the value of the Entry's text, the values could now be
|
||||
// out-of-sync; re-sync them and force the TextBox cursor to the end of the text
|
||||
string entryText = Element.Text;
|
||||
if (Control.Text != entryText)
|
||||
{
|
||||
Control.Text = entryText;
|
||||
if (Control.Text != null)
|
||||
Control.SelectionStart = Control.Text.Length;
|
||||
}
|
||||
|
||||
_ignoreTextChange = false;
|
||||
}
|
||||
|
||||
void UpdateAlignment()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
|
||||
}
|
||||
|
||||
void UpdateColor()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Entry entry = Element;
|
||||
if (entry != null)
|
||||
{
|
||||
if (!IsNullOrEmpty(entry.Text))
|
||||
{
|
||||
if (!entry.TextColor.IsDefault)
|
||||
Control.Foreground = entry.TextColor.ToBrush();
|
||||
else
|
||||
Control.Foreground = (Brush)WControl.ForegroundProperty.GetMetadata(typeof(FormsTextBox)).DefaultValue;
|
||||
|
||||
// Force the PhoneTextBox control to do some internal bookkeeping
|
||||
// so the colors change immediately and remain changed when the control gets focus
|
||||
Control.OnApplyTemplate();
|
||||
}
|
||||
}
|
||||
else
|
||||
Control.Foreground = (Brush)WControl.ForegroundProperty.GetMetadata(typeof(FormsTextBox)).DefaultValue;
|
||||
}
|
||||
|
||||
void UpdateFont()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Entry entry = Element;
|
||||
|
||||
if (entry == null)
|
||||
return;
|
||||
|
||||
bool entryIsDefault = entry.FontFamily == null && entry.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Entry), true) && entry.FontAttributes == FontAttributes.None;
|
||||
|
||||
if (entryIsDefault && !_fontApplied)
|
||||
return;
|
||||
|
||||
if (entryIsDefault)
|
||||
{
|
||||
Control.ClearValue(WControl.FontStyleProperty);
|
||||
Control.ClearValue(WControl.FontSizeProperty);
|
||||
Control.ClearValue(WControl.FontFamilyProperty);
|
||||
Control.ClearValue(WControl.FontWeightProperty);
|
||||
Control.ClearValue(WControl.FontStretchProperty);
|
||||
}
|
||||
else
|
||||
Control.ApplyFont(entry);
|
||||
|
||||
_fontApplied = true;
|
||||
}
|
||||
|
||||
void UpdateInputScope()
|
||||
{
|
||||
Control.InputScope = Element.Keyboard.ToInputScope();
|
||||
}
|
||||
|
||||
void UpdateIsPassword()
|
||||
{
|
||||
Control.IsPassword = Element.IsPassword;
|
||||
}
|
||||
|
||||
void UpdatePlaceholder()
|
||||
{
|
||||
//Control.Hint = Element.Placeholder ?? "";
|
||||
}
|
||||
|
||||
void UpdatePlaceholderColor()
|
||||
{
|
||||
Color placeholderColor = Element.PlaceholderColor;
|
||||
|
||||
if (placeholderColor.IsDefault)
|
||||
{
|
||||
if (_placeholderDefaultBrush == null)
|
||||
return;
|
||||
|
||||
// Use the cached default brush
|
||||
Control.PlaceholderForegroundBrush = _placeholderDefaultBrush;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_placeholderDefaultBrush == null)
|
||||
{
|
||||
// Cache the default brush in case we need to set the color back to default
|
||||
_placeholderDefaultBrush = Control.PlaceholderForegroundBrush;
|
||||
}
|
||||
|
||||
Control.PlaceholderForegroundBrush = placeholderColor.ToBrush();
|
||||
}
|
||||
|
||||
void UpdateText()
|
||||
{
|
||||
// If the text property has changed because TextBoxOnTextChanged called SetValueFromRenderer,
|
||||
// we don't want to re-update the text and reset the cursor position
|
||||
if (_ignoreTextChange)
|
||||
return;
|
||||
|
||||
if (Control.Text == Element.Text)
|
||||
return;
|
||||
|
||||
Control.Text = Element.Text ?? "";
|
||||
Control.Select(Control.Text == null ? 0 : Control.Text.Length, 0);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.LostFocus -= OnTextBoxUnfocused;
|
||||
Control.TextChanged -= TextBoxOnTextChanged;
|
||||
Control.KeyUp -= TextBoxOnKeyUp;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class FrameRenderer : ViewRenderer<Frame, Border>
|
||||
{
|
||||
VisualElement _currentView;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new Border());
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateContent();
|
||||
UpdateBorder();
|
||||
UpdateCornerRadius();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Frame.ContentProperty.PropertyName)
|
||||
UpdateContent();
|
||||
else if (e.PropertyName == Frame.OutlineColorProperty.PropertyName || e.PropertyName == Frame.HasShadowProperty.PropertyName)
|
||||
UpdateBorder();
|
||||
else if (e.PropertyName == Frame.CornerRadiusProperty.PropertyName)
|
||||
UpdateCornerRadius();
|
||||
}
|
||||
|
||||
protected override void UpdateBackground()
|
||||
{
|
||||
Control.UpdateDependencyColor(Border.BackgroundProperty, Element.BackgroundColor);
|
||||
}
|
||||
|
||||
void UpdateContent()
|
||||
{
|
||||
if (_currentView != null)
|
||||
{
|
||||
_currentView.Cleanup(); // cleanup old view
|
||||
}
|
||||
|
||||
_currentView = Element.Content;
|
||||
Control.Child = _currentView != null ? Platform.GetOrCreateRenderer(_currentView).GetNativeElement() : null;
|
||||
}
|
||||
|
||||
void UpdateBorder()
|
||||
{
|
||||
if (Element.OutlineColor != Color.Default)
|
||||
{
|
||||
Control.UpdateDependencyColor(Border.BorderBrushProperty, Element.OutlineColor);
|
||||
Control.BorderThickness = new System.Windows.Thickness(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Control.UpdateDependencyColor(Border.BorderBrushProperty, new Color(0, 0, 0, 0));
|
||||
Control.BorderThickness = new System.Windows.Thickness(0);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCornerRadius()
|
||||
{
|
||||
Control.CornerRadius = new CornerRadius(Element.CornerRadius >= 0 ? Element.CornerRadius : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Xamarin.Forms.Internals;
|
||||
using WImage = System.Windows.Controls.Image;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class ImageRenderer : ViewRenderer<Image, WImage>
|
||||
{
|
||||
protected override async void OnElementChanged(ElementChangedEventArgs<Image> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WImage());
|
||||
}
|
||||
|
||||
// Update control property
|
||||
await TryUpdateSource();
|
||||
UpdateAspect();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Image.SourceProperty.PropertyName)
|
||||
await TryUpdateSource();
|
||||
else if (e.PropertyName == Image.AspectProperty.PropertyName)
|
||||
UpdateAspect();
|
||||
}
|
||||
|
||||
void UpdateAspect()
|
||||
{
|
||||
Control.Stretch = Element.Aspect.ToStretch();
|
||||
if (Element.Aspect == Aspect.AspectFill) // Then Center Crop
|
||||
{
|
||||
Control.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
Control.VerticalAlignment = VerticalAlignment.Center;
|
||||
}
|
||||
else // Default
|
||||
{
|
||||
Control.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
Control.VerticalAlignment = VerticalAlignment.Top;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task TryUpdateSource()
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateSource().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(nameof(ImageRenderer), "Error loading image: {0}", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Element.SetIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task UpdateSource()
|
||||
{
|
||||
if (Element == null || Control == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Element.SetIsLoading(true);
|
||||
|
||||
ImageSource source = Element.Source;
|
||||
IImageSourceHandler handler;
|
||||
if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
|
||||
{
|
||||
System.Windows.Media.ImageSource imagesource;
|
||||
|
||||
try
|
||||
{
|
||||
imagesource = await handler.LoadImageAsync(source);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
imagesource = null;
|
||||
}
|
||||
|
||||
// In the time it takes to await the imagesource, some zippy little app
|
||||
// might have disposed of this Image already.
|
||||
if (Control != null)
|
||||
{
|
||||
Control.Source = imagesource;
|
||||
}
|
||||
|
||||
RefreshImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
Control.Source = null;
|
||||
Element.SetIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshImage()
|
||||
{
|
||||
((IVisualElementController)Element)?.InvalidateMeasure(InvalidationTrigger.RendererReady);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IImageSourceHandler : IRegisterable
|
||||
{
|
||||
Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancelationToken = default(CancellationToken));
|
||||
}
|
||||
|
||||
public sealed class FileImageSourceHandler : IImageSourceHandler
|
||||
{
|
||||
public Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancelationToken = new CancellationToken())
|
||||
{
|
||||
System.Windows.Media.ImageSource image = null;
|
||||
FileImageSource filesource = imagesoure as FileImageSource;
|
||||
if (filesource != null)
|
||||
{
|
||||
string file = filesource.File;
|
||||
image = new BitmapImage(new Uri(file, UriKind.RelativeOrAbsolute));
|
||||
}
|
||||
return Task.FromResult(image);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class StreamImageSourceHandler : IImageSourceHandler
|
||||
{
|
||||
public async Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = new CancellationToken())
|
||||
{
|
||||
BitmapImage bitmapimage = null;
|
||||
StreamImageSource streamsource = imagesource as StreamImageSource;
|
||||
if (streamsource != null && streamsource.Stream != null)
|
||||
{
|
||||
using (Stream stream = await ((IStreamImageSource)streamsource).GetStreamAsync(cancelationToken))
|
||||
{
|
||||
bitmapimage = new BitmapImage()
|
||||
{
|
||||
StreamSource = stream
|
||||
};
|
||||
}
|
||||
}
|
||||
return bitmapimage;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UriImageSourceHandler : IImageSourceHandler
|
||||
{
|
||||
public async Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancelationToken = new CancellationToken())
|
||||
{
|
||||
BitmapImage bitmapimage = null;
|
||||
var imageLoader = imagesoure as UriImageSource;
|
||||
if (imageLoader?.Uri != null)
|
||||
{
|
||||
bitmapimage = new BitmapImage();
|
||||
bitmapimage.BeginInit();
|
||||
bitmapimage.UriSource = imageLoader.Uri;
|
||||
bitmapimage.EndInit();
|
||||
}
|
||||
return bitmapimage;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class LabelRenderer : ViewRenderer<Label, TextBlock>
|
||||
{
|
||||
bool _fontApplied;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new TextBlock());
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateText();
|
||||
UpdateColor();
|
||||
UpdateAlign();
|
||||
UpdateFont();
|
||||
UpdateLineBreakMode();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Label.TextProperty.PropertyName || e.PropertyName == Label.FormattedTextProperty.PropertyName)
|
||||
UpdateText();
|
||||
else if (e.PropertyName == Label.TextColorProperty.PropertyName)
|
||||
UpdateColor();
|
||||
else if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName || e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName)
|
||||
UpdateAlign();
|
||||
else if (e.PropertyName == Label.FontProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Label.LineBreakModeProperty.PropertyName)
|
||||
UpdateLineBreakMode();
|
||||
}
|
||||
|
||||
protected override void UpdateBackground()
|
||||
{
|
||||
Control.UpdateDependencyColor(TextBlock.BackgroundProperty, Element.BackgroundColor);
|
||||
}
|
||||
|
||||
void UpdateAlign()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Label label = Element;
|
||||
if (label == null)
|
||||
return;
|
||||
|
||||
Control.TextAlignment = label.HorizontalTextAlignment.ToNativeTextAlignment();
|
||||
}
|
||||
|
||||
void UpdateColor()
|
||||
{
|
||||
if (Control == null || Element == null)
|
||||
return;
|
||||
|
||||
if (Element.TextColor != Color.Default)
|
||||
Control.Foreground = Element.TextColor.ToBrush();
|
||||
else
|
||||
Control.Foreground = Brushes.Black;
|
||||
}
|
||||
|
||||
void UpdateFont()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Label label = Element;
|
||||
if (label == null || (label.IsDefault() && !_fontApplied))
|
||||
return;
|
||||
|
||||
#pragma warning disable 618
|
||||
Font fontToApply = label.IsDefault() ? Font.SystemFontOfSize(NamedSize.Medium) : label.Font;
|
||||
#pragma warning restore 618
|
||||
|
||||
Control.ApplyFont(fontToApply);
|
||||
_fontApplied = true;
|
||||
}
|
||||
|
||||
void UpdateLineBreakMode()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
switch (Element.LineBreakMode)
|
||||
{
|
||||
case LineBreakMode.NoWrap:
|
||||
Control.TextTrimming = TextTrimming.None;
|
||||
Control.TextWrapping = TextWrapping.NoWrap;
|
||||
break;
|
||||
case LineBreakMode.WordWrap:
|
||||
Control.TextTrimming = TextTrimming.None;
|
||||
Control.TextWrapping = TextWrapping.Wrap;
|
||||
break;
|
||||
case LineBreakMode.CharacterWrap:
|
||||
Control.TextTrimming = TextTrimming.CharacterEllipsis;
|
||||
Control.TextWrapping = TextWrapping.Wrap;
|
||||
break;
|
||||
case LineBreakMode.HeadTruncation:
|
||||
Control.TextTrimming = TextTrimming.WordEllipsis;
|
||||
Control.TextWrapping = TextWrapping.NoWrap;
|
||||
break;
|
||||
case LineBreakMode.TailTruncation:
|
||||
Control.TextTrimming = TextTrimming.CharacterEllipsis;
|
||||
Control.TextWrapping = TextWrapping.NoWrap;
|
||||
break;
|
||||
case LineBreakMode.MiddleTruncation:
|
||||
Control.TextTrimming = TextTrimming.WordEllipsis;
|
||||
Control.TextWrapping = TextWrapping.NoWrap;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateText()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
Label label = Element;
|
||||
if (label != null)
|
||||
{
|
||||
if (label.FormattedText == null)
|
||||
Control.Text = label.Text;
|
||||
else
|
||||
{
|
||||
FormattedString formattedText = label.FormattedText ?? label.Text;
|
||||
|
||||
Control.Inlines.Clear();
|
||||
foreach (Inline inline in formattedText.ToInlines())
|
||||
Control.Inlines.Add(inline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Platform.WPF.Helpers;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class LayoutRenderer : ViewRenderer<Layout, FormsPanel>
|
||||
{
|
||||
IElementController ElementController => Element as IElementController;
|
||||
bool _isZChanged;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Layout> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new FormsPanel(Element));
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateClipToBounds();
|
||||
foreach (Element child in ElementController.LogicalChildren)
|
||||
HandleChildAdded(Element, new ElementEventArgs(child));
|
||||
|
||||
// Suscribe element event
|
||||
Element.ChildAdded += HandleChildAdded;
|
||||
Element.ChildRemoved += HandleChildRemoved;
|
||||
Element.ChildrenReordered += HandleChildrenReordered;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void Appearing()
|
||||
{
|
||||
base.Appearing();
|
||||
Element.Layout(new Rectangle(0, 0, Control.ActualWidth, Control.ActualHeight));
|
||||
}
|
||||
|
||||
void HandleChildAdded(object sender, ElementEventArgs e)
|
||||
{
|
||||
UiHelper.ExecuteInUiThread(() =>
|
||||
{
|
||||
var view = e.Element as VisualElement;
|
||||
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
IVisualElementRenderer renderer;
|
||||
Platform.SetRenderer(view, renderer = Platform.CreateRenderer(view));
|
||||
Control.Children.Add(renderer.GetNativeElement());
|
||||
if (_isZChanged)
|
||||
EnsureZIndex();
|
||||
});
|
||||
}
|
||||
|
||||
void HandleChildRemoved(object sender, ElementEventArgs e)
|
||||
{
|
||||
UiHelper.ExecuteInUiThread(() =>
|
||||
{
|
||||
var view = e.Element as VisualElement;
|
||||
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
FrameworkElement native = Platform.GetRenderer(view)?.GetNativeElement() as FrameworkElement;
|
||||
if (native != null)
|
||||
{
|
||||
Control.Children.Remove(native);
|
||||
view.Cleanup();
|
||||
if (_isZChanged)
|
||||
EnsureZIndex();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void HandleChildrenReordered(object sender, EventArgs e)
|
||||
{
|
||||
EnsureZIndex();
|
||||
}
|
||||
|
||||
void EnsureZIndex()
|
||||
{
|
||||
if (ElementController.LogicalChildren.Count == 0)
|
||||
return;
|
||||
|
||||
for (var z = 0; z < ElementController.LogicalChildren.Count; z++)
|
||||
{
|
||||
var child = ElementController.LogicalChildren[z] as VisualElement;
|
||||
if (child == null)
|
||||
continue;
|
||||
|
||||
IVisualElementRenderer childRenderer = Platform.GetRenderer(child);
|
||||
|
||||
if (childRenderer == null)
|
||||
continue;
|
||||
|
||||
if (Canvas.GetZIndex(childRenderer.GetNativeElement()) != (z + 1))
|
||||
{
|
||||
if (!_isZChanged)
|
||||
_isZChanged = true;
|
||||
|
||||
Canvas.SetZIndex(childRenderer.GetNativeElement(), z + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName)
|
||||
UpdateClipToBounds();
|
||||
}
|
||||
|
||||
protected override void UpdateBackground()
|
||||
{
|
||||
Control.UpdateDependencyColor(FormsPanel.BackgroundProperty, Element.BackgroundColor);
|
||||
}
|
||||
|
||||
protected override void UpdateNativeWidget()
|
||||
{
|
||||
base.UpdateNativeWidget();
|
||||
UpdateClipToBounds();
|
||||
}
|
||||
|
||||
void UpdateClipToBounds()
|
||||
{
|
||||
Control.Clip = null;
|
||||
if (Element.IsClippedToBounds)
|
||||
Control.Clip = new RectangleGeometry { Rect = new Rect(0, 0, Control.ActualWidth, Control.ActualHeight) };
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Element != null)
|
||||
{
|
||||
Element.ChildAdded -= HandleChildAdded;
|
||||
Element.ChildRemoved -= HandleChildRemoved;
|
||||
Element.ChildrenReordered -= HandleChildrenReordered;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
using WList = System.Windows.Controls.ListView;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class ListViewRenderer : ViewRenderer<ListView, WList>
|
||||
{
|
||||
ITemplatedItemsView<Cell> TemplatedItemsView => Element;
|
||||
|
||||
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
|
||||
result.Minimum = new Size(40, 40);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
|
||||
{
|
||||
if (e.OldElement != null) // Clear old element event
|
||||
{
|
||||
var templatedItems = ((ITemplatedItemsView<Cell>)e.OldElement).TemplatedItems;
|
||||
templatedItems.CollectionChanged -= TemplatedItems_GroupedCollectionChanged;
|
||||
templatedItems.GroupedCollectionChanged -= TemplatedItems_GroupedCollectionChanged;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
var listView = new WList
|
||||
{
|
||||
DataContext = Element,
|
||||
ItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["CellTemplate"],
|
||||
Style = (System.Windows.Style)System.Windows.Application.Current.Resources["ListViewTemplate"]
|
||||
};
|
||||
SetNativeControl(listView);
|
||||
Control.SelectionChanged += OnNativeSelectionChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateItemSource();
|
||||
|
||||
//UpdateHeader();
|
||||
//UpdateFooter();
|
||||
//UpdateJumpList();
|
||||
|
||||
// Suscribe element event
|
||||
TemplatedItemsView.TemplatedItems.CollectionChanged += TemplatedItems_GroupedCollectionChanged;
|
||||
TemplatedItemsView.TemplatedItems.GroupedCollectionChanged += TemplatedItems_GroupedCollectionChanged;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
private void TemplatedItems_GroupedCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateItemSource();
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == ListView.IsGroupingEnabledProperty.PropertyName)
|
||||
{
|
||||
//UpdateGrouping();
|
||||
}
|
||||
|
||||
|
||||
/*if (e.PropertyName == ListView.SelectedItemProperty.PropertyName)
|
||||
OnItemSelected(Element.SelectedItem);
|
||||
else if (e.PropertyName == "HeaderElement")
|
||||
UpdateHeader();
|
||||
else if (e.PropertyName == "FooterElement")
|
||||
UpdateFooter();
|
||||
else if ((e.PropertyName == ListView.IsRefreshingProperty.PropertyName) || (e.PropertyName == ListView.IsPullToRefreshEnabledProperty.PropertyName) || (e.PropertyName == "CanRefresh"))
|
||||
UpdateIsRefreshing();
|
||||
else if (e.PropertyName == "GroupShortNameBinding")
|
||||
UpdateJumpList();*/
|
||||
}
|
||||
|
||||
|
||||
void UpdateItemSource()
|
||||
{
|
||||
List<object> items = new List<object>();
|
||||
if (Element.IsGroupingEnabled)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var groupItem in TemplatedItemsView.TemplatedItems)
|
||||
{
|
||||
var group = TemplatedItemsView.TemplatedItems.GetGroup(index);
|
||||
|
||||
if (group.Count != 0)
|
||||
{
|
||||
items.Add(group.HeaderContent);
|
||||
|
||||
/*if (HasHeader(group))
|
||||
_cells.Add(GetCell(group.HeaderContent));
|
||||
else
|
||||
_cells.Add(CreateEmptyHeader());*/
|
||||
|
||||
items.AddRange(group);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
Control.ItemsSource = items;
|
||||
}
|
||||
else
|
||||
{
|
||||
Control.ItemsSource = Element.TemplatedItems;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OnNativeSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
Element.NotifyRowTapped(Control.SelectedIndex, cell:null);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.SelectionChanged -= OnNativeSelectionChanged;
|
||||
}
|
||||
|
||||
if (Element != null)
|
||||
{
|
||||
TemplatedItemsView.TemplatedItems.CollectionChanged -= TemplatedItems_GroupedCollectionChanged;
|
||||
TemplatedItemsView.TemplatedItems.GroupedCollectionChanged -= TemplatedItems_GroupedCollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WpfLightToolkit.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class MasterDetailPageRenderer : VisualPageRenderer<MasterDetailPage, LightMasterDetailPage>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<MasterDetailPage> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new LightMasterDetailPage() { ContentLoader = new FormsContentLoader() });
|
||||
|
||||
DependencyPropertyDescriptor.FromProperty(LightMasterDetailPage.IsPresentedProperty, typeof(LightMasterDetailPage))
|
||||
.AddValueChanged(Control, OnIsPresentedChanged);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName) // || e.PropertyName == MasterDetailPage.MasterBehaviorProperty.PropertyName)
|
||||
UpdateIsPresented();
|
||||
else if (e.PropertyName == "Master")
|
||||
UpdateMasterPage();
|
||||
else if (e.PropertyName == "Detail")
|
||||
UpdateDetailPage();
|
||||
}
|
||||
|
||||
protected override void Appearing()
|
||||
{
|
||||
base.Appearing();
|
||||
UpdateIsPresented();
|
||||
UpdateMasterPage();
|
||||
UpdateDetailPage();
|
||||
}
|
||||
|
||||
void UpdateIsPresented()
|
||||
{
|
||||
Control.IsPresented = Element.IsPresented;
|
||||
}
|
||||
|
||||
void UpdateMasterPage()
|
||||
{
|
||||
Control.MasterPage = Element.Master;
|
||||
}
|
||||
|
||||
void UpdateDetailPage()
|
||||
{
|
||||
Control.DetailPage = Element.Detail;
|
||||
}
|
||||
|
||||
private void OnIsPresentedChanged(object sender, EventArgs arg)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, Control.IsPresented);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
DependencyPropertyDescriptor.FromProperty(LightMasterDetailPage.IsPresentedProperty, typeof(LightMasterDetailPage))
|
||||
.RemoveValueChanged(Control, OnIsPresentedChanged);
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WpfLightToolkit.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class FormsLightNavigationPage : LightNavigationPage
|
||||
{
|
||||
NavigationPage NavigationPage;
|
||||
|
||||
public FormsLightNavigationPage(NavigationPage navigationPage)
|
||||
{
|
||||
ContentLoader = new FormsContentLoader();
|
||||
NavigationPage = navigationPage;
|
||||
}
|
||||
|
||||
public override void OnBackButtonPressed()
|
||||
{
|
||||
NavigationPage.PopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class NavigationPageRenderer : VisualPageRenderer<NavigationPage, FormsLightNavigationPage>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
|
||||
{
|
||||
if (e.OldElement != null) // Clear old element event
|
||||
{
|
||||
e.OldElement.PushRequested -= Element_PushRequested;
|
||||
e.OldElement.PopRequested -= Element_PopRequested;
|
||||
e.OldElement.PopToRootRequested -= Element_PopToRootRequested;
|
||||
e.OldElement.RemovePageRequested -= Element_RemovePageRequested;
|
||||
e.OldElement.InsertPageBeforeRequested -= Element_InsertPageBeforeRequested;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new FormsLightNavigationPage(Element));
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateBarBackgroundColor();
|
||||
UpdateBarTextColor();
|
||||
|
||||
// Suscribe element event
|
||||
Element.PushRequested += Element_PushRequested;
|
||||
Element.PopRequested += Element_PopRequested;
|
||||
Element.PopToRootRequested += Element_PopToRootRequested;
|
||||
Element.RemovePageRequested += Element_RemovePageRequested;
|
||||
Element.InsertPageBeforeRequested += Element_InsertPageBeforeRequested;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
|
||||
UpdateBarBackgroundColor();
|
||||
else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
|
||||
UpdateBarTextColor();
|
||||
}
|
||||
|
||||
protected override void Appearing()
|
||||
{
|
||||
base.Appearing();
|
||||
PushExistingNavigationStack();
|
||||
}
|
||||
|
||||
void Element_InsertPageBeforeRequested(object sender, Internals.NavigationRequestedEventArgs e)
|
||||
{
|
||||
this.Control?.InsertPageBefore(e.Page, e.BeforePage);
|
||||
}
|
||||
|
||||
void Element_RemovePageRequested(object sender, Internals.NavigationRequestedEventArgs e)
|
||||
{
|
||||
this.Control?.RemovePage(e.Page);
|
||||
}
|
||||
|
||||
void Element_PopToRootRequested(object sender, Internals.NavigationRequestedEventArgs e)
|
||||
{
|
||||
this.Control?.PopToRoot(e.Animated);
|
||||
}
|
||||
|
||||
void Element_PopRequested(object sender, Internals.NavigationRequestedEventArgs e)
|
||||
{
|
||||
this.Control?.Pop(e.Animated);
|
||||
}
|
||||
|
||||
void Element_PushRequested(object sender, Internals.NavigationRequestedEventArgs e)
|
||||
{
|
||||
this.Control?.Push(e.Page, e.Animated);
|
||||
}
|
||||
|
||||
void PushExistingNavigationStack()
|
||||
{
|
||||
foreach (var page in Element.Pages)
|
||||
{
|
||||
Control.InternalChildren.Add(page);
|
||||
}
|
||||
this.Control.CurrentPage = this.Control.InternalChildren.Last();
|
||||
}
|
||||
|
||||
void UpdateBarBackgroundColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(LightNavigationPage.TitleBarBackgroundColorProperty, Element.BarBackgroundColor);
|
||||
}
|
||||
|
||||
void UpdateBarTextColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(LightNavigationPage.TitleBarTextColorProperty, Element.BarTextColor);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Element != null)
|
||||
{
|
||||
Element.PushRequested -= Element_PushRequested;
|
||||
Element.PopRequested -= Element_PopRequested;
|
||||
Element.PopToRootRequested -= Element_PopToRootRequested;
|
||||
Element.RemovePageRequested -= Element_RemovePageRequested;
|
||||
Element.InsertPageBeforeRequested -= Element_InsertPageBeforeRequested;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using System;
|
||||
using System.Windows.Threading;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Forms.Integration;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class OpenGLViewRenderer : ViewRenderer<OpenGLView, WindowsFormsHost>
|
||||
{
|
||||
private GLControl _glControl;
|
||||
private DispatcherTimer _timer;
|
||||
private Action<Rectangle> _action;
|
||||
private bool _hasRenderLoop;
|
||||
private bool _disposed;
|
||||
|
||||
public Action<Rectangle> Action
|
||||
{
|
||||
get { return _action; }
|
||||
set { _action = value; }
|
||||
}
|
||||
|
||||
public bool HasRenderLoop
|
||||
{
|
||||
get { return _hasRenderLoop; }
|
||||
set { _hasRenderLoop = value; }
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed && disposing)
|
||||
{
|
||||
_disposed = true;
|
||||
|
||||
if (Element != null)
|
||||
((IOpenGlViewController)Element).DisplayRequested -= Render;
|
||||
|
||||
if(_glControl != null)
|
||||
_glControl.Paint -= OnPaint;
|
||||
|
||||
if(_timer != null)
|
||||
_timer.Tick -= OnTick;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<OpenGLView> e)
|
||||
{
|
||||
if (e.OldElement != null)
|
||||
((IOpenGlViewController)e.OldElement).DisplayRequested -= Render;
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
var windowsFormsHost = new WindowsFormsHost();
|
||||
_glControl = new GLControl(new GraphicsMode(32, 24), 2, 0, GraphicsContextFlags.Default);
|
||||
_glControl.MakeCurrent();
|
||||
_glControl.Dock = DockStyle.Fill;
|
||||
|
||||
_glControl.Paint += OnPaint;
|
||||
|
||||
windowsFormsHost.Child = _glControl;
|
||||
SetNativeControl(windowsFormsHost);
|
||||
|
||||
_timer = new DispatcherTimer();
|
||||
_timer.Interval = TimeSpan.FromMilliseconds(16);
|
||||
_timer.Tick += OnTick;
|
||||
_timer.Start();
|
||||
|
||||
((IOpenGlViewController)e.NewElement).DisplayRequested += Render;
|
||||
|
||||
SetRenderMode();
|
||||
SetupRenderAction();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == OpenGLView.HasRenderLoopProperty.PropertyName)
|
||||
{
|
||||
SetRenderMode();
|
||||
SetupRenderAction();
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(object sender, EventArgs eventArgs)
|
||||
{
|
||||
if (HasRenderLoop)
|
||||
return;
|
||||
|
||||
SetupRenderAction();
|
||||
}
|
||||
|
||||
private void SetRenderMode()
|
||||
{
|
||||
HasRenderLoop = Element.HasRenderLoop;
|
||||
}
|
||||
|
||||
private void SetupRenderAction()
|
||||
{
|
||||
var model = Element;
|
||||
var onDisplay = model.OnDisplay;
|
||||
|
||||
Action = onDisplay;
|
||||
}
|
||||
|
||||
private void OnPaint(object sender, PaintEventArgs e)
|
||||
{
|
||||
if(_glControl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_glControl.MakeCurrent();
|
||||
Action.Invoke(new Rectangle(0, 0, _glControl.Width, _glControl.Height));
|
||||
_glControl.SwapBuffers();
|
||||
}
|
||||
|
||||
private void OnTick(object sender, EventArgs e)
|
||||
{
|
||||
if (!HasRenderLoop)
|
||||
return;
|
||||
|
||||
_glControl.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using WpfLightToolkit.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class PageRenderer : VisualPageRenderer<Page, LightContentPage>
|
||||
{
|
||||
VisualElement _currentView;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new LightContentPage());
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateContent();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if(e.PropertyName == ContentPage.ContentProperty.PropertyName)
|
||||
UpdateContent();
|
||||
}
|
||||
|
||||
void UpdateContent()
|
||||
{
|
||||
ContentPage page = Element as ContentPage;
|
||||
if (page != null)
|
||||
{
|
||||
if (_currentView != null)
|
||||
{
|
||||
_currentView.Cleanup(); // cleanup old view
|
||||
}
|
||||
|
||||
_currentView = page.Content;
|
||||
Control.Content = _currentView != null ? Platform.GetOrCreateRenderer(_currentView).GetNativeElement() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class PickerRenderer : ViewRenderer<Picker, ComboBox>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new ComboBox());
|
||||
Control.SelectionChanged += OnControlSelectionChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateTitle();
|
||||
UpdateSelectedIndex();
|
||||
UpdateTextColor();
|
||||
Control.ItemsSource = ((LockableObservableListWrapper)Element.Items)._list;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Picker.TitleProperty.PropertyName)
|
||||
{
|
||||
UpdateTitle();
|
||||
}
|
||||
else if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
|
||||
{
|
||||
UpdateSelectedIndex();
|
||||
}
|
||||
else if (e.PropertyName == Picker.TextColorProperty.PropertyName)
|
||||
{
|
||||
UpdateTextColor();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTitle()
|
||||
{
|
||||
//TODO: Create full size combobox
|
||||
}
|
||||
|
||||
void UpdateTextColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(ComboBox.ForegroundProperty, Element.TextColor);
|
||||
}
|
||||
|
||||
void UpdateSelectedIndex()
|
||||
{
|
||||
Control.SelectedIndex = Element.SelectedIndex;
|
||||
}
|
||||
|
||||
private void OnControlSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (Element != null)
|
||||
Element.SelectedIndex = Control.SelectedIndex;
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.SelectionChanged -= OnControlSelectionChanged;
|
||||
Control.ItemsSource = null;
|
||||
}
|
||||
|
||||
if (Element != null)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
using WProgressBar = System.Windows.Controls.ProgressBar;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class ProgressBarRenderer : ViewRenderer<ProgressBar, WProgressBar>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WProgressBar { Minimum = 0, Maximum = 1, Foreground = Brushes.DeepSkyBlue });
|
||||
Control.ValueChanged += HandleValueChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateProgress();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == ProgressBar.ProgressProperty.PropertyName)
|
||||
UpdateProgress();
|
||||
}
|
||||
|
||||
void UpdateProgress()
|
||||
{
|
||||
Control.Value = Element.Progress;
|
||||
}
|
||||
|
||||
void HandleValueChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
((IVisualElementController)Element)?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.ValueChanged -= HandleValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class ScrollViewRenderer : ViewRenderer<ScrollView, ScrollViewer>
|
||||
{
|
||||
VisualElement _currentView;
|
||||
Animatable _animatable;
|
||||
|
||||
protected IScrollViewController Controller
|
||||
{
|
||||
get { return Element; }
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e)
|
||||
{
|
||||
if (e.OldElement != null) // Clear old element event
|
||||
{
|
||||
((IScrollViewController)e.OldElement).ScrollToRequested -= OnScrollToRequested;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new ScrollViewer() { IsManipulationEnabled = true, PanningMode = PanningMode.Both });
|
||||
Control.LayoutUpdated += NativeLayoutUpdated;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateOrientation();
|
||||
LoadContent();
|
||||
|
||||
// Suscribe element event
|
||||
Controller.ScrollToRequested += OnScrollToRequested;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == "Content")
|
||||
LoadContent();
|
||||
else if (e.PropertyName == Layout.PaddingProperty.PropertyName)
|
||||
UpdateMargins();
|
||||
else if (e.PropertyName == ScrollView.OrientationProperty.PropertyName)
|
||||
UpdateOrientation();
|
||||
}
|
||||
|
||||
void NativeLayoutUpdated(object sender, EventArgs e)
|
||||
{
|
||||
UpdateScrollPosition();
|
||||
}
|
||||
|
||||
static double GetDistance(double start, double position, double v)
|
||||
{
|
||||
return start + (position - start) * v;
|
||||
}
|
||||
|
||||
void LoadContent()
|
||||
{
|
||||
if (_currentView != null)
|
||||
{
|
||||
_currentView.Cleanup(); // cleanup old view
|
||||
}
|
||||
|
||||
_currentView = Element.Content;
|
||||
|
||||
if(_currentView != null)
|
||||
{
|
||||
/*
|
||||
* Wrap Content in a DockPanel : The goal is to reduce ce Measure Cycle on scolling
|
||||
*/
|
||||
DockPanel dockPanel = new DockPanel();
|
||||
dockPanel.Children.Add(Platform.GetOrCreateRenderer(_currentView).GetNativeElement());
|
||||
Control.Content = dockPanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
Control.Content = null;
|
||||
}
|
||||
UpdateMargins();
|
||||
}
|
||||
|
||||
void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
|
||||
{
|
||||
if (_animatable == null && e.ShouldAnimate)
|
||||
_animatable = new Animatable();
|
||||
|
||||
ScrollToPosition position = e.Position;
|
||||
double x = e.ScrollX;
|
||||
double y = e.ScrollY;
|
||||
|
||||
if (e.Mode == ScrollToMode.Element)
|
||||
{
|
||||
Point itemPosition = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
|
||||
x = itemPosition.X;
|
||||
y = itemPosition.Y;
|
||||
}
|
||||
|
||||
if (Control.VerticalOffset == y && Control.HorizontalOffset == x)
|
||||
return;
|
||||
|
||||
if (e.ShouldAnimate)
|
||||
{
|
||||
var animation = new Animation(v => { UpdateScrollOffset(GetDistance(Control.ViewportWidth, x, v), GetDistance(Control.ViewportHeight, y, v)); });
|
||||
|
||||
animation.Commit(_animatable, "ScrollTo", length: 500, easing: Easing.CubicInOut, finished: (v, d) =>
|
||||
{
|
||||
UpdateScrollOffset(x, y);
|
||||
Controller.SendScrollFinished();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateScrollOffset(x, y);
|
||||
Controller.SendScrollFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateMargins()
|
||||
{
|
||||
var element = Control.Content as FrameworkElement;
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
switch (Element.Orientation)
|
||||
{
|
||||
case ScrollOrientation.Horizontal:
|
||||
// need to add left/right margins
|
||||
element.Margin = new System.Windows.Thickness(Element.Padding.Left, 0, 10, 0);
|
||||
break;
|
||||
case ScrollOrientation.Vertical:
|
||||
// need to add top/bottom margins
|
||||
element.Margin = new System.Windows.Thickness(0, Element.Padding.Top, 0, Element.Padding.Bottom);
|
||||
break;
|
||||
case ScrollOrientation.Both:
|
||||
// need to add all margins
|
||||
element.Margin = new System.Windows.Thickness(Element.Padding.Left, Element.Padding.Top, Element.Padding.Right, Element.Padding.Bottom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOrientation()
|
||||
{
|
||||
if (Element.Orientation == ScrollOrientation.Horizontal || Element.Orientation == ScrollOrientation.Both)
|
||||
Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
else
|
||||
Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
|
||||
|
||||
if (Element.Orientation == ScrollOrientation.Vertical || Element.Orientation == ScrollOrientation.Both)
|
||||
Control.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
else
|
||||
Control.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
|
||||
}
|
||||
|
||||
void UpdateScrollOffset(double x, double y)
|
||||
{
|
||||
if (Element.Orientation == ScrollOrientation.Horizontal)
|
||||
Control.ScrollToHorizontalOffset(x);
|
||||
else
|
||||
Control.ScrollToVerticalOffset(y);
|
||||
}
|
||||
|
||||
void UpdateScrollPosition()
|
||||
{
|
||||
if (Element != null)
|
||||
Controller.SetScrolledPosition(Control.HorizontalOffset, Control.VerticalOffset);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.LayoutUpdated -= NativeLayoutUpdated;
|
||||
}
|
||||
|
||||
if (Element != null)
|
||||
{
|
||||
Controller.ScrollToRequested -= OnScrollToRequested;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class SearchBarRenderer : ViewRenderer<SearchBar, FormsTextBox>
|
||||
{
|
||||
const string DefaultPlaceholder = "Search";
|
||||
Brush _defaultPlaceholderColorBrush;
|
||||
Brush _defaultTextColorBrush;
|
||||
bool _fontApplied;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
var scope = new InputScope();
|
||||
var name = new InputScopeName();
|
||||
//name.NameValue = InputScopeNameValue.;
|
||||
scope.Names.Add(name);
|
||||
|
||||
SetNativeControl(new FormsTextBox { InputScope = scope });
|
||||
Control.KeyUp += PhoneTextBoxOnKeyUp;
|
||||
Control.TextChanged += PhoneTextBoxOnTextChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateText();
|
||||
UpdatePlaceholder();
|
||||
UpdateAlignment();
|
||||
UpdateFont();
|
||||
UpdatePlaceholderColor();
|
||||
UpdateTextColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == SearchBar.TextProperty.PropertyName)
|
||||
UpdateText();
|
||||
else if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName)
|
||||
UpdatePlaceholder();
|
||||
else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
|
||||
UpdateAlignment();
|
||||
else if (e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
|
||||
UpdatePlaceholderColor();
|
||||
else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
|
||||
UpdateTextColor();
|
||||
}
|
||||
|
||||
void PhoneTextBoxOnKeyUp(object sender, KeyEventArgs keyEventArgs)
|
||||
{
|
||||
if (keyEventArgs.Key == Key.Enter)
|
||||
((ISearchBarController)Element).OnSearchButtonPressed();
|
||||
}
|
||||
|
||||
void PhoneTextBoxOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, Control.Text);
|
||||
}
|
||||
|
||||
void UpdateAlignment()
|
||||
{
|
||||
Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
|
||||
}
|
||||
|
||||
void UpdateFont()
|
||||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
SearchBar searchbar = Element;
|
||||
|
||||
if (searchbar == null)
|
||||
return;
|
||||
|
||||
bool searchbarIsDefault = searchbar.FontFamily == null && searchbar.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(SearchBar), true) && searchbar.FontAttributes == FontAttributes.None;
|
||||
|
||||
if (searchbarIsDefault && !_fontApplied)
|
||||
return;
|
||||
|
||||
if (searchbarIsDefault)
|
||||
{
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontStyleProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontSizeProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontFamilyProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontWeightProperty);
|
||||
Control.ClearValue(System.Windows.Controls.Control.FontStretchProperty);
|
||||
}
|
||||
else
|
||||
Control.ApplyFont(searchbar);
|
||||
|
||||
_fontApplied = true;
|
||||
}
|
||||
|
||||
void UpdatePlaceholder()
|
||||
{
|
||||
//Control.Hint = Element.Placeholder ?? DefaultPlaceholder;
|
||||
}
|
||||
|
||||
void UpdatePlaceholderColor()
|
||||
{
|
||||
Color placeholderColor = Element.PlaceholderColor;
|
||||
|
||||
if (placeholderColor.IsDefault)
|
||||
{
|
||||
if (_defaultPlaceholderColorBrush == null)
|
||||
return;
|
||||
|
||||
Control.PlaceholderForegroundBrush = _defaultPlaceholderColorBrush;
|
||||
}
|
||||
|
||||
if (_defaultPlaceholderColorBrush == null)
|
||||
_defaultPlaceholderColorBrush = Control.PlaceholderForegroundBrush;
|
||||
|
||||
Control.PlaceholderForegroundBrush = placeholderColor.ToBrush();
|
||||
}
|
||||
|
||||
void UpdateText()
|
||||
{
|
||||
Control.Text = Element.Text ?? "";
|
||||
}
|
||||
|
||||
void UpdateTextColor()
|
||||
{
|
||||
Color textColor = Element.TextColor;
|
||||
|
||||
if (textColor.IsDefault)
|
||||
{
|
||||
if (_defaultTextColorBrush == null)
|
||||
return;
|
||||
|
||||
Control.Foreground = _defaultTextColorBrush;
|
||||
}
|
||||
|
||||
if (_defaultTextColorBrush == null)
|
||||
_defaultTextColorBrush = Control.Foreground;
|
||||
|
||||
Control.Foreground = textColor.ToBrush();
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.KeyUp -= PhoneTextBoxOnKeyUp;
|
||||
Control.TextChanged -= PhoneTextBoxOnTextChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WSlider = System.Windows.Controls.Slider;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class SliderRenderer : ViewRenderer<Slider, WSlider>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Slider> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WSlider());
|
||||
Control.ValueChanged += HandleValueChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateMinimum();
|
||||
UpdateMaximum();
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Slider.MinimumProperty.PropertyName)
|
||||
UpdateMinimum();
|
||||
else if (e.PropertyName == Slider.MaximumProperty.PropertyName)
|
||||
UpdateMaximum();
|
||||
else if (e.PropertyName == Slider.ValueProperty.PropertyName)
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
void UpdateMinimum()
|
||||
{
|
||||
Control.Minimum = Element.Minimum;
|
||||
}
|
||||
|
||||
void UpdateMaximum()
|
||||
{
|
||||
Control.Maximum = Element.Maximum;
|
||||
}
|
||||
|
||||
void UpdateValue()
|
||||
{
|
||||
if (Control.Value != Element.Value)
|
||||
Control.Value = Element.Value;
|
||||
}
|
||||
|
||||
void HandleValueChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(Slider.ValueProperty, Control.Value);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.ValueChanged -= HandleValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using WButton = System.Windows.Controls.Button;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class StepperRenderer : ViewRenderer<Stepper, Border>
|
||||
{
|
||||
readonly StackPanel _panel = new StackPanel();
|
||||
WButton _downButton;
|
||||
WButton _upButton;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(CreateControl());
|
||||
_upButton.Click += UpButtonOnClick;
|
||||
_downButton.Click += DownButtonOnClick;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if(e.PropertyName == Stepper.MinimumProperty.PropertyName ||e.PropertyName == Stepper.MaximumProperty.PropertyName ||
|
||||
e.PropertyName == Stepper.ValueProperty.PropertyName)
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
Border CreateControl()
|
||||
{
|
||||
var border = new Border() { Child = _panel };
|
||||
_panel.HorizontalAlignment = HorizontalAlignment.Right;
|
||||
_panel.Orientation = Orientation.Horizontal;
|
||||
|
||||
_upButton = new WButton { Content = "+", Width = 100 };
|
||||
_downButton = new WButton { Content = "-", Width = 100 };
|
||||
|
||||
_panel.Children.Add(_downButton);
|
||||
_panel.Children.Add(_upButton);
|
||||
return border;
|
||||
}
|
||||
|
||||
void DownButtonOnClick(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, Math.Max(Element.Minimum, Element.Value - Element.Increment));
|
||||
}
|
||||
|
||||
void UpButtonOnClick(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, Math.Min(Element.Maximum, Element.Value + Element.Increment));
|
||||
}
|
||||
|
||||
void UpdateButtons()
|
||||
{
|
||||
_upButton.IsEnabled = Element.Value < Element.Maximum;
|
||||
_downButton.IsEnabled = Element.Value > Element.Minimum;
|
||||
}
|
||||
|
||||
protected override void UpdateEnabled()
|
||||
{
|
||||
_panel.IsEnabled = Element.IsEnabled;
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
_upButton.Click -= UpButtonOnClick;
|
||||
_downButton.Click -= DownButtonOnClick;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class SwitchRenderer : ViewRenderer<Switch, CheckBox>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new CheckBox());
|
||||
Control.Checked += OnNativeToggled;
|
||||
Control.Unchecked += OnNativeToggled;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
UpdateIsToggled();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Switch.IsToggledProperty.PropertyName)
|
||||
{
|
||||
UpdateIsToggled();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateIsToggled()
|
||||
{
|
||||
Control.IsChecked = Element.IsToggled;
|
||||
}
|
||||
|
||||
void OnNativeToggled(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(Switch.IsToggledProperty, Control.IsChecked);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.Checked -= OnNativeToggled;
|
||||
Control.Unchecked -= OnNativeToggled;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WpfLightToolkit.Controls;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class TabbedPageRenderer : VisualMultiPageRenderer<TabbedPage, Page, LightTabbedPage>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new LightTabbedPage() { ContentLoader = new FormsContentLoader() });
|
||||
}
|
||||
|
||||
UpdateBarBackgroundColor();
|
||||
UpdateBarTextColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == TabbedPage.BarBackgroundColorProperty.PropertyName)
|
||||
UpdateBarBackgroundColor();
|
||||
else if (e.PropertyName == TabbedPage.BarTextColorProperty.PropertyName)
|
||||
UpdateBarTextColor();
|
||||
}
|
||||
|
||||
void UpdateBarBackgroundColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(LightTabbedPage.BarBackgroundColorProperty, Element.BarBackgroundColor);
|
||||
}
|
||||
|
||||
void UpdateBarTextColor()
|
||||
{
|
||||
Control.UpdateDependencyColor(LightTabbedPage.BarTextColorProperty, Element.BarTextColor);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using WList = System.Windows.Controls.ListView;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class TableViewDataTemplateSelector : System.Windows.Controls.DataTemplateSelector
|
||||
{
|
||||
public override System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container)
|
||||
{
|
||||
if(item is Cell)
|
||||
return System.Windows.Application.Current.MainWindow.FindResource("CellTemplate") as System.Windows.DataTemplate;
|
||||
else
|
||||
return System.Windows.Application.Current.MainWindow.FindResource("TableSectionHeader") as System.Windows.DataTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
public class TableViewRenderer : ViewRenderer<TableView, WList>
|
||||
{
|
||||
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
|
||||
result.Minimum = new Size(40, 40);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TableView> e)
|
||||
{
|
||||
if (e.OldElement != null)
|
||||
{
|
||||
Element.ModelChanged -= OnModelChanged;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
var listView = new WList
|
||||
{
|
||||
ItemTemplateSelector = new TableViewDataTemplateSelector(),
|
||||
Style = (System.Windows.Style)System.Windows.Application.Current.Resources["TableViewTemplate"],
|
||||
};
|
||||
|
||||
SetNativeControl(listView);
|
||||
Control.SelectionChanged += Control_SelectionChanged;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
Control.ItemsSource = GetTableViewRow();
|
||||
|
||||
// Element event
|
||||
Element.ModelChanged += OnModelChanged;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
|
||||
private void Control_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
foreach (object item in e.AddedItems)
|
||||
{
|
||||
Cell cell = item as Cell;
|
||||
if (cell != null)
|
||||
{
|
||||
if (cell.IsEnabled)
|
||||
Element.Model.RowSelected(cell);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Control.SelectedItem = null;
|
||||
}
|
||||
|
||||
void OnModelChanged(object sender, EventArgs eventArgs)
|
||||
{
|
||||
Control.ItemsSource = GetTableViewRow();
|
||||
}
|
||||
|
||||
public IList<object> GetTableViewRow()
|
||||
{
|
||||
List<object> result = new List<object>();
|
||||
|
||||
foreach (var item in Element.Root)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(item.Title))
|
||||
result.Add(item.Title);
|
||||
|
||||
result.AddRange(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.SelectionChanged -= Control_SelectionChanged;
|
||||
}
|
||||
|
||||
if(Element != null)
|
||||
{
|
||||
Element.ModelChanged -= OnModelChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using WControl = System.Windows.Controls.Control;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class DefaultViewRenderer : ViewRenderer<View, UserControl>
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
|
||||
{
|
||||
base.OnElementChanged(e);
|
||||
SetNativeControl(new UserControl());
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewRenderer<TElement, TNativeElement> : IVisualElementRenderer, IEffectControlProvider
|
||||
where TElement : VisualElement where TNativeElement : FrameworkElement
|
||||
{
|
||||
readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers =
|
||||
new List<EventHandler<VisualElementChangedEventArgs>>();
|
||||
|
||||
VisualElementTracker _tracker;
|
||||
|
||||
IElementController ElementController => Element as IElementController;
|
||||
|
||||
public TNativeElement Control { get; private set; }
|
||||
|
||||
public TElement Element { get; private set; }
|
||||
|
||||
protected virtual bool AutoTrack { get; set; } = true;
|
||||
|
||||
protected VisualElementTracker Tracker
|
||||
{
|
||||
get { return _tracker; }
|
||||
set
|
||||
{
|
||||
if (_tracker == value)
|
||||
return;
|
||||
|
||||
if (_tracker != null)
|
||||
{
|
||||
_tracker.Dispose();
|
||||
_tracker.Updated -= HandleTrackerUpdated;
|
||||
}
|
||||
|
||||
_tracker = value;
|
||||
|
||||
if (_tracker != null)
|
||||
_tracker.Updated += HandleTrackerUpdated;
|
||||
}
|
||||
}
|
||||
void IEffectControlProvider.RegisterEffect(Effect effect)
|
||||
{
|
||||
PlatformEffect platformEffect = effect as PlatformEffect;
|
||||
if (platformEffect != null)
|
||||
OnRegisterEffect(platformEffect);
|
||||
}
|
||||
|
||||
VisualElement IVisualElementRenderer.Element
|
||||
{
|
||||
get { return Element; }
|
||||
}
|
||||
|
||||
public FrameworkElement GetNativeElement()
|
||||
{
|
||||
return Control;
|
||||
}
|
||||
|
||||
event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
|
||||
{
|
||||
add { _elementChangedHandlers.Add(value); }
|
||||
remove { _elementChangedHandlers.Remove(value); }
|
||||
}
|
||||
|
||||
public virtual SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if (Control == null)
|
||||
return new SizeRequest();
|
||||
|
||||
var constraint = new System.Windows.Size(widthConstraint, heightConstraint);
|
||||
|
||||
Control.Measure(constraint);
|
||||
|
||||
return new SizeRequest(new Size(Math.Ceiling(Control.DesiredSize.Width), Math.Ceiling(Control.DesiredSize.Height)));
|
||||
}
|
||||
|
||||
public void SetElement(VisualElement element)
|
||||
{
|
||||
TElement oldElement = Element;
|
||||
Element = (TElement)element;
|
||||
|
||||
if (oldElement != null)
|
||||
{
|
||||
oldElement.PropertyChanged -= OnElementPropertyChanged;
|
||||
oldElement.FocusChangeRequested -= OnModelFocusChangeRequested;
|
||||
}
|
||||
|
||||
Element.PropertyChanged += OnElementPropertyChanged;
|
||||
Element.FocusChangeRequested += OnModelFocusChangeRequested;
|
||||
|
||||
OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, Element));
|
||||
|
||||
var controller = (IElementController)oldElement;
|
||||
if (controller != null && controller.EffectControlProvider == this)
|
||||
controller.EffectControlProvider = null;
|
||||
|
||||
controller = element;
|
||||
if (controller != null)
|
||||
controller.EffectControlProvider = this;
|
||||
}
|
||||
|
||||
public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
|
||||
|
||||
protected virtual void OnElementChanged(ElementChangedEventArgs<TElement> e)
|
||||
{
|
||||
var args = new VisualElementChangedEventArgs(e.OldElement, e.NewElement);
|
||||
for (var i = 0; i < _elementChangedHandlers.Count; i++)
|
||||
_elementChangedHandlers[i](this, args);
|
||||
|
||||
UpdateRequests();
|
||||
ElementChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
|
||||
UpdateEnabled();
|
||||
else if (e.PropertyName == Frame.HeightRequestProperty.PropertyName)
|
||||
UpdateRequests();
|
||||
else if (e.PropertyName == Frame.WidthRequestProperty.PropertyName)
|
||||
UpdateRequests();
|
||||
else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
|
||||
UpdateBackground();
|
||||
else if (e.PropertyName == View.HorizontalOptionsProperty.PropertyName || e.PropertyName == View.VerticalOptionsProperty.PropertyName)
|
||||
UpdateAlignment();
|
||||
}
|
||||
|
||||
protected virtual void OnGotFocus(object sender, RoutedEventArgs args)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
|
||||
}
|
||||
|
||||
protected virtual void OnLostFocus(object sender, RoutedEventArgs args)
|
||||
{
|
||||
((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
|
||||
}
|
||||
|
||||
protected virtual void OnRegisterEffect(PlatformEffect effect)
|
||||
{
|
||||
effect.SetControl(Control);
|
||||
}
|
||||
|
||||
protected void SetNativeControl(TNativeElement native)
|
||||
{
|
||||
Control = native;
|
||||
|
||||
if (AutoTrack && Tracker == null)
|
||||
Tracker = new VisualElementTracker<TElement, FrameworkElement> { Element = Element, Control = Control };
|
||||
|
||||
Element.IsNativeStateConsistent = false;
|
||||
|
||||
Control.Loaded += (sender, e) =>
|
||||
{
|
||||
Element.IsNativeStateConsistent = true;
|
||||
Appearing();
|
||||
};
|
||||
Control.Unloaded += (sender, e) => { Disappearing(); };
|
||||
|
||||
Control.GotFocus += OnGotFocus;
|
||||
Control.LostFocus += OnLostFocus;
|
||||
|
||||
UpdateBackground();
|
||||
UpdateAlignment();
|
||||
}
|
||||
|
||||
protected virtual void Appearing()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Disappearing()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void UpdateBackground()
|
||||
{
|
||||
var control = Control as WControl;
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
control.UpdateDependencyColor(WControl.BackgroundProperty, Element.BackgroundColor);
|
||||
}
|
||||
|
||||
protected virtual void UpdateRequests()
|
||||
{
|
||||
if (Control == null || Element == null)
|
||||
return;
|
||||
|
||||
Control.Width = Element.WidthRequest >= 0 ? Element.WidthRequest : Double.NaN;
|
||||
Control.Height = Element.HeightRequest >= 0 ? Element.HeightRequest : Double.NaN;
|
||||
}
|
||||
|
||||
protected virtual void UpdateNativeWidget()
|
||||
{
|
||||
UpdateEnabled();
|
||||
}
|
||||
|
||||
internal virtual void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
|
||||
{
|
||||
var control = Control as WControl;
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
if (args.Focus)
|
||||
args.Result = control.Focus();
|
||||
else
|
||||
{
|
||||
UnfocusControl(control);
|
||||
args.Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal void UnfocusControl(WControl control)
|
||||
{
|
||||
if (control == null || !control.IsEnabled)
|
||||
return;
|
||||
control.IsEnabled = false;
|
||||
control.IsEnabled = true;
|
||||
}
|
||||
|
||||
void HandleTrackerUpdated(object sender, EventArgs e)
|
||||
{
|
||||
UpdateNativeWidget();
|
||||
}
|
||||
|
||||
protected virtual void UpdateEnabled()
|
||||
{
|
||||
WControl wcontrol = Control as WControl;
|
||||
if (wcontrol != null)
|
||||
wcontrol.IsEnabled = Element.IsEnabled;
|
||||
}
|
||||
|
||||
void UpdateAlignment()
|
||||
{
|
||||
View view = Element as View;
|
||||
if (view != null)
|
||||
{
|
||||
Control.HorizontalAlignment = view.HorizontalOptions.ToNativeHorizontalAlignment();
|
||||
Control.VerticalAlignment = view.VerticalOptions.ToNativeVerticalAlignment();
|
||||
}
|
||||
}
|
||||
|
||||
bool _disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing || _disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
|
||||
if (Control != null)
|
||||
{
|
||||
//Console.WriteLine("Dispose : " + this.Control.GetType());
|
||||
Control.GotFocus -= OnGotFocus;
|
||||
Control.LostFocus -= OnLostFocus;
|
||||
}
|
||||
|
||||
if (Element != null)
|
||||
{
|
||||
Element.PropertyChanged -= OnElementPropertyChanged;
|
||||
Element.FocusChangeRequested -= OnModelFocusChangeRequested;
|
||||
}
|
||||
|
||||
Tracker = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WpfLightToolkit.Controls;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class VisualMultiPageRenderer<TElement, TContainer, TNativeElement> : VisualPageRenderer<TElement, TNativeElement>
|
||||
where TElement : MultiPage<TContainer>
|
||||
where TNativeElement : LightMultiPage
|
||||
where TContainer : Page
|
||||
{
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<TElement> e)
|
||||
{
|
||||
if (e.OldElement != null) // Clear old element event
|
||||
{
|
||||
((INotifyCollectionChanged)e.OldElement.Children).CollectionChanged -= OnPagesChanged;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
// Subscribe control event
|
||||
Control.SelectionChanged += Control_SelectionChanged;
|
||||
|
||||
// Subscribe element event
|
||||
((INotifyCollectionChanged)Element.Children).CollectionChanged += OnPagesChanged;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void Appearing()
|
||||
{
|
||||
base.Appearing();
|
||||
OnPagesChanged(Element.Children, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
UpdateCurrentPage();
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == nameof(MultiPage<TContainer>.CurrentPage))
|
||||
UpdateCurrentPage();
|
||||
}
|
||||
|
||||
void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
e.Apply(Element.Children, Control.ItemsSource);
|
||||
}
|
||||
|
||||
void UpdateCurrentPage()
|
||||
{
|
||||
Control.SelectedItem = Element.CurrentPage;
|
||||
}
|
||||
|
||||
private void Control_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
Element.CurrentPage = e.NewElement as TContainer;
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.SelectionChanged -= Control_SelectionChanged;
|
||||
}
|
||||
|
||||
if (Element != null)
|
||||
{
|
||||
((INotifyCollectionChanged)Element.Children).CollectionChanged -= OnPagesChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using WpfLightToolkit.Controls;
|
||||
using WpfLightToolkit.Extensions;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class VisualPageRenderer<TElement, TNativeElement> : ViewRenderer<TElement, TNativeElement>
|
||||
where TElement : Page
|
||||
where TNativeElement : LightPage
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<TElement> e)
|
||||
{
|
||||
if (e.OldElement != null) // Clear old element event
|
||||
{
|
||||
((ObservableCollection<ToolbarItem>)e.OldElement.ToolbarItems).CollectionChanged -= VisualPageRenderer_CollectionChanged;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
// Update control property
|
||||
UpdateTitle();
|
||||
UpdateBackButton();
|
||||
UpdateBackButtonTitle();
|
||||
UpdateNavigationBarVisible();
|
||||
UpdateToolbar();
|
||||
|
||||
// Suscribe element event
|
||||
((ObservableCollection<ToolbarItem>)Element.ToolbarItems).CollectionChanged += VisualPageRenderer_CollectionChanged;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
|
||||
UpdateBackground();
|
||||
else if (e.PropertyName == Page.TitleProperty.PropertyName)
|
||||
UpdateTitle();
|
||||
else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName)
|
||||
UpdateBackButton();
|
||||
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
|
||||
UpdateBackButtonTitle();
|
||||
else if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
|
||||
UpdateNavigationBarVisible();
|
||||
|
||||
}
|
||||
|
||||
void UpdateTitle()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(Element.Title))
|
||||
Control.Title = Element.Title;
|
||||
}
|
||||
|
||||
void UpdateBackButton()
|
||||
{
|
||||
this.Control.HasBackButton = NavigationPage.GetHasBackButton(Element);
|
||||
}
|
||||
|
||||
void UpdateBackButtonTitle()
|
||||
{
|
||||
this.Control.BackButtonTitle = NavigationPage.GetBackButtonTitle(Element);
|
||||
}
|
||||
|
||||
void UpdateNavigationBarVisible()
|
||||
{
|
||||
this.Control.HasNavigationBar = NavigationPage.GetHasNavigationBar(Element);
|
||||
}
|
||||
|
||||
protected override void UpdateBackground()
|
||||
{
|
||||
string bgImage = Element.BackgroundImage;
|
||||
if (!string.IsNullOrEmpty(bgImage))
|
||||
{
|
||||
ImageBrush imgBrush = new ImageBrush()
|
||||
{
|
||||
ImageSource = new BitmapImage(new Uri(bgImage, UriKind.RelativeOrAbsolute))
|
||||
};
|
||||
Control.Background = imgBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.UpdateBackground();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateToolbar()
|
||||
{
|
||||
Control.PrimaryTopBarCommands.Clear();
|
||||
Control.SecondaryTopBarCommands.Clear();
|
||||
|
||||
foreach (var item in Element.ToolbarItems)
|
||||
{
|
||||
LightAppBarButton appBar = new LightAppBarButton()
|
||||
{
|
||||
Label = item.Text,
|
||||
Tag = item
|
||||
};
|
||||
|
||||
appBar.SetValue(FrameworkElementAttached.PriorityProperty, item.Priority);
|
||||
|
||||
if(item.Icon != null)
|
||||
{
|
||||
Symbol symbol;
|
||||
Geometry geometry;
|
||||
|
||||
if (Enum.TryParse(item.Icon.File, true, out symbol))
|
||||
appBar.Icon = new LightSymbolIcon() { Symbol = symbol };
|
||||
else if (TryParseGeometry(item.Icon.File, out geometry))
|
||||
appBar.Icon = new LightPathIcon() { Data = geometry };
|
||||
else if (Path.GetExtension(item.Icon.File) != null)
|
||||
appBar.Icon = new LightBitmapIcon() { UriSource = new Uri(item.Icon.File, UriKind.RelativeOrAbsolute) };
|
||||
}
|
||||
|
||||
appBar.Click += (sender, e) =>
|
||||
{
|
||||
if (appBar.Tag != null && appBar.Tag is ToolbarItem)
|
||||
{
|
||||
(appBar.Tag as ToolbarItem).Activate();
|
||||
}
|
||||
};
|
||||
|
||||
if (item.Order == ToolbarItemOrder.Default || item.Order == ToolbarItemOrder.Primary)
|
||||
Control.PrimaryTopBarCommands.Add(appBar);
|
||||
else
|
||||
Control.SecondaryTopBarCommands.Add(appBar);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Appearing()
|
||||
{
|
||||
base.Appearing();
|
||||
Element?.SendAppearing();
|
||||
}
|
||||
|
||||
protected override void Disappearing()
|
||||
{
|
||||
Element?.SendDisappearing();
|
||||
base.Disappearing();
|
||||
}
|
||||
|
||||
private void VisualPageRenderer_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateToolbar();
|
||||
}
|
||||
|
||||
private bool TryParseGeometry(string value, out Geometry geometry)
|
||||
{
|
||||
geometry = null;
|
||||
try
|
||||
{
|
||||
geometry = Geometry.Parse(value);
|
||||
return true;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Element != null)
|
||||
{
|
||||
((ObservableCollection<ToolbarItem>)Element.ToolbarItems).CollectionChanged -= VisualPageRenderer_CollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Threading;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class WebViewRenderer : ViewRenderer<WebView, WebBrowser>, IWebViewDelegate
|
||||
{
|
||||
WebNavigationEvent _eventState;
|
||||
bool _updating;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
|
||||
{
|
||||
if (e.OldElement != null) // Clear old element event
|
||||
{
|
||||
e.OldElement.EvalRequested -= OnEvalRequested;
|
||||
e.OldElement.GoBackRequested -= OnGoBackRequested;
|
||||
e.OldElement.GoForwardRequested -= OnGoForwardRequested;
|
||||
}
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null) // construct and SetNativeControl and suscribe control event
|
||||
{
|
||||
SetNativeControl(new WebBrowser());
|
||||
Control.Navigated += WebBrowserOnNavigated;
|
||||
Control.Navigating += WebBrowserOnNavigating;
|
||||
}
|
||||
|
||||
// Update control property
|
||||
Load();
|
||||
|
||||
// Suscribe element event
|
||||
Element.EvalRequested += OnEvalRequested;
|
||||
Element.GoBackRequested += OnGoBackRequested;
|
||||
Element.GoForwardRequested += OnGoForwardRequested;
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == WebView.SourceProperty.PropertyName)
|
||||
{
|
||||
if (!_updating)
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
void Load()
|
||||
{
|
||||
if (Element.Source != null)
|
||||
Element.Source.Load(this);
|
||||
|
||||
UpdateCanGoBackForward();
|
||||
}
|
||||
|
||||
public async void LoadHtml(string html, string baseUrl)
|
||||
{
|
||||
if (html == null)
|
||||
return;
|
||||
|
||||
string fileName = string.Format("formslocal_{0}.html", DateTime.Now.Ticks);
|
||||
|
||||
await SaveToIsoStore(fileName, html);
|
||||
Control.Navigate(new Uri(fileName, UriKind.Relative));
|
||||
}
|
||||
|
||||
public void LoadUrl(string url)
|
||||
{
|
||||
if (url == null)
|
||||
return;
|
||||
|
||||
Control.Source = new Uri(url, UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
|
||||
void OnEvalRequested(object sender, EvalRequested eventArg)
|
||||
{
|
||||
Control.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => Control.InvokeScript("eval", eventArg.Script)));
|
||||
}
|
||||
|
||||
void OnGoBackRequested(object sender, EventArgs eventArgs)
|
||||
{
|
||||
if (Control.CanGoBack)
|
||||
{
|
||||
_eventState = WebNavigationEvent.Back;
|
||||
Control.GoBack();
|
||||
}
|
||||
|
||||
UpdateCanGoBackForward();
|
||||
}
|
||||
|
||||
void OnGoForwardRequested(object sender, EventArgs eventArgs)
|
||||
{
|
||||
if (Control.CanGoForward)
|
||||
{
|
||||
_eventState = WebNavigationEvent.Forward;
|
||||
Control.GoForward();
|
||||
}
|
||||
UpdateCanGoBackForward();
|
||||
}
|
||||
|
||||
async Task SaveToIsoStore(string fileName, string html)
|
||||
{
|
||||
IIsolatedStorageFile store = Device.PlatformServices.GetUserStoreForApplication();
|
||||
using (var file = await store.OpenFileAsync(fileName, FileMode.CreateNew, FileAccess.Write).ConfigureAwait(false))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(html);
|
||||
await file.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SendNavigated(UrlWebViewSource source, WebNavigationEvent evnt, WebNavigationResult result)
|
||||
{
|
||||
Console.WriteLine("SendNavigated : " + source.Url);
|
||||
_updating = true;
|
||||
((IElementController)Element).SetValueFromRenderer(WebView.SourceProperty, source);
|
||||
_updating = false;
|
||||
|
||||
Element.SendNavigated(new WebNavigatedEventArgs(evnt, source, source.Url, result));
|
||||
|
||||
UpdateCanGoBackForward();
|
||||
_eventState = WebNavigationEvent.NewPage;
|
||||
}
|
||||
|
||||
void UpdateCanGoBackForward()
|
||||
{
|
||||
((IWebViewController)Element).CanGoBack = Control.CanGoBack;
|
||||
((IWebViewController)Element).CanGoForward = Control.CanGoForward;
|
||||
}
|
||||
|
||||
void WebBrowserOnNavigated(object sender, System.Windows.Navigation.NavigationEventArgs navigationEventArgs)
|
||||
{
|
||||
Console.WriteLine("WebBrowserOnNavigated");
|
||||
|
||||
string url = navigationEventArgs.Uri.IsAbsoluteUri ? navigationEventArgs.Uri.AbsoluteUri : navigationEventArgs.Uri.OriginalString;
|
||||
SendNavigated(new UrlWebViewSource { Url = url }, _eventState, WebNavigationResult.Success);
|
||||
|
||||
UpdateCanGoBackForward();
|
||||
}
|
||||
|
||||
void WebBrowserOnNavigating(object sender, NavigatingCancelEventArgs navigatingEventArgs)
|
||||
{
|
||||
string url = navigatingEventArgs.Uri.IsAbsoluteUri ? navigatingEventArgs.Uri.AbsoluteUri : navigatingEventArgs.Uri.OriginalString;
|
||||
var args = new WebNavigatingEventArgs(_eventState, new UrlWebViewSource { Url = url }, url);
|
||||
|
||||
Element.SendNavigating(args);
|
||||
|
||||
navigatingEventArgs.Cancel = args.Cancel;
|
||||
|
||||
// reset in this case because this is the last event we will get
|
||||
if (args.Cancel)
|
||||
_eventState = WebNavigationEvent.NewPage;
|
||||
}
|
||||
|
||||
void WebBrowserOnNavigationFailed(object sender, NavigationFailedEventArgs navigationFailedEventArgs)
|
||||
{
|
||||
string url = navigationFailedEventArgs.Uri.IsAbsoluteUri ? navigationFailedEventArgs.Uri.AbsoluteUri : navigationFailedEventArgs.Uri.OriginalString;
|
||||
SendNavigated(new UrlWebViewSource { Url = url }, _eventState, WebNavigationResult.Failure);
|
||||
}
|
||||
|
||||
bool _isDisposed;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.Navigated -= WebBrowserOnNavigated;
|
||||
Control.Navigating -= WebBrowserOnNavigating;
|
||||
Control.Source = null;
|
||||
Control.Dispose();
|
||||
}
|
||||
|
||||
if (Element != null)
|
||||
{
|
||||
Element.EvalRequested -= OnEvalRequested;
|
||||
Element.GoBackRequested -= OnGoBackRequested;
|
||||
Element.GoForwardRequested -= OnGoForwardRequested;
|
||||
}
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal class ResourcesProvider : ISystemResourcesProvider
|
||||
{
|
||||
ResourceDictionary _dictionary;
|
||||
|
||||
public IResourceDictionary GetSystemResources()
|
||||
{
|
||||
_dictionary = new ResourceDictionary();
|
||||
|
||||
UpdateStyles();
|
||||
|
||||
return _dictionary;
|
||||
}
|
||||
|
||||
Style GetStyle(System.Windows.Style style, TextBlock hackbox)
|
||||
{
|
||||
hackbox.Style = style;
|
||||
|
||||
var result = new Style(typeof(Label));
|
||||
result.Setters.Add(new Setter { Property = Label.FontFamilyProperty, Value = hackbox.FontFamily });
|
||||
result.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = hackbox.FontSize });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void UpdateStyles()
|
||||
{
|
||||
var textBlock = new TextBlock();
|
||||
_dictionary[Device.Styles.TitleStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["HeaderTextBlockStyle"], textBlock);
|
||||
_dictionary[Device.Styles.SubtitleStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["SubheaderTextBlockStyle"], textBlock);
|
||||
_dictionary[Device.Styles.BodyStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["BodyTextBlockStyle"], textBlock);
|
||||
_dictionary[Device.Styles.CaptionStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["CaptionTextBlockStyle"], textBlock);
|
||||
_dictionary[Device.Styles.ListItemTextStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["BaseTextBlockStyle"], textBlock);
|
||||
_dictionary[Device.Styles.ListItemDetailTextStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["BodyTextBlockStyle"], textBlock);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public abstract class VisualElementTracker : IDisposable
|
||||
{
|
||||
public abstract void Dispose();
|
||||
|
||||
public event EventHandler Updated;
|
||||
|
||||
protected void OnUpdated()
|
||||
{
|
||||
Updated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public class VisualElementTracker<TElement, TNativeElement> : VisualElementTracker where TElement : VisualElement where TNativeElement : FrameworkElement
|
||||
{
|
||||
bool _disposed;
|
||||
TNativeElement _control;
|
||||
TElement _element;
|
||||
|
||||
bool _invalidateArrangeNeeded;
|
||||
bool _isPanning;
|
||||
bool _isPinching;
|
||||
|
||||
bool _touchFrameReportedEventSet;
|
||||
int _touchPoints = 1;
|
||||
|
||||
public TNativeElement Control
|
||||
{
|
||||
get { return _control; }
|
||||
set
|
||||
{
|
||||
if (_control == value)
|
||||
return;
|
||||
|
||||
if (_control != null)
|
||||
{
|
||||
_control.MouseLeftButtonUp -= MouseLeftButtonUp;
|
||||
_control.ManipulationDelta -= OnManipulationDelta;
|
||||
_control.ManipulationCompleted -= OnManipulationCompleted;
|
||||
}
|
||||
|
||||
_control = value;
|
||||
|
||||
if (_control != null)
|
||||
{
|
||||
_control.MouseLeftButtonUp += MouseLeftButtonUp;
|
||||
_control.ManipulationDelta += OnManipulationDelta;
|
||||
_control.ManipulationCompleted += OnManipulationCompleted;
|
||||
}
|
||||
UpdateNativeControl();
|
||||
}
|
||||
}
|
||||
|
||||
public TElement Element
|
||||
{
|
||||
get { return _element; }
|
||||
set
|
||||
{
|
||||
if (_element == value)
|
||||
return;
|
||||
|
||||
if (_element != null)
|
||||
{
|
||||
_element.BatchCommitted -= HandleRedrawNeeded;
|
||||
_element.PropertyChanged -= HandlePropertyChanged;
|
||||
}
|
||||
|
||||
_element = value;
|
||||
|
||||
if (_element != null)
|
||||
{
|
||||
_element.BatchCommitted += HandleRedrawNeeded;
|
||||
_element.PropertyChanged += HandlePropertyChanged;
|
||||
}
|
||||
|
||||
UpdateNativeControl();
|
||||
}
|
||||
}
|
||||
|
||||
private void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var fe = (sender as FrameworkElement);
|
||||
var vr = (sender as DefaultViewRenderer)?.Element;
|
||||
|
||||
if ((fe != null && !fe.IsEnabled) || (vr != null && !vr.IsEnabled))
|
||||
return;
|
||||
|
||||
e.Handled = ElementOnTap(e.ClickCount);
|
||||
}
|
||||
|
||||
protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (Element.Batched)
|
||||
{
|
||||
if (e.PropertyName == VisualElement.XProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.YProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.WidthProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.HeightProperty.PropertyName)
|
||||
_invalidateArrangeNeeded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.PropertyName == VisualElement.XProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.YProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.WidthProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.HeightProperty.PropertyName)
|
||||
MaybeInvalidate();
|
||||
else if (e.PropertyName == VisualElement.AnchorXProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.AnchorYProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.ScaleProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.TranslationXProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.TranslationYProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.RotationProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.RotationXProperty.PropertyName ||
|
||||
e.PropertyName == VisualElement.RotationYProperty.PropertyName)
|
||||
UpdateScaleAndTranslateAndRotation();
|
||||
else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
|
||||
UpdateVisibility();
|
||||
else if (e.PropertyName == VisualElement.OpacityProperty.PropertyName)
|
||||
UpdateOpacity();
|
||||
else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
|
||||
UpdateInputTransparent();
|
||||
}
|
||||
|
||||
protected virtual void UpdateNativeControl()
|
||||
{
|
||||
if (Element == null || Control == null)
|
||||
return;
|
||||
|
||||
UpdateOpacity();
|
||||
UpdateScaleAndTranslateAndRotation();
|
||||
UpdateInputTransparent();
|
||||
UpdateVisibility();
|
||||
|
||||
if (_invalidateArrangeNeeded)
|
||||
MaybeInvalidate();
|
||||
_invalidateArrangeNeeded = false;
|
||||
|
||||
UpdateTouchFrameReportedEvent();
|
||||
|
||||
OnUpdated();
|
||||
}
|
||||
|
||||
bool ElementOnTap(int numberOfTapsRequired)
|
||||
{
|
||||
var view = Element as View;
|
||||
if (view == null)
|
||||
return false;
|
||||
|
||||
var result = false;
|
||||
foreach (TapGestureRecognizer gestureRecognizer in
|
||||
view.GestureRecognizers.OfType<TapGestureRecognizer>().Where(g => g.NumberOfTapsRequired == numberOfTapsRequired))
|
||||
{
|
||||
gestureRecognizer.SendTapped(view);
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HandlePan(ManipulationDeltaEventArgs e, View view)
|
||||
{
|
||||
foreach (PanGestureRecognizer recognizer in
|
||||
view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Where(g => g.TouchPoints == _touchPoints))
|
||||
{
|
||||
if (!_isPanning)
|
||||
((IPanGestureController)recognizer).SendPanStarted(view, Application.Current.PanGestureId);
|
||||
|
||||
double totalX = 0;
|
||||
double totalY = 0;
|
||||
|
||||
((IPanGestureController)recognizer).SendPan(view, totalX, totalY, Application.Current.PanGestureId);
|
||||
_isPanning = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleRedrawNeeded(object sender, EventArgs e)
|
||||
{
|
||||
UpdateNativeControl();
|
||||
}
|
||||
|
||||
void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
|
||||
{
|
||||
var view = Element as View;
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
IEnumerable pinchGestures = view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>();
|
||||
foreach (var recognizer in pinchGestures)
|
||||
((IPinchGestureController)recognizer).SendPinchEnded(view);
|
||||
_isPinching = false;
|
||||
|
||||
IEnumerable<PanGestureRecognizer> panGestures = view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Where(g => g.TouchPoints == _touchPoints);
|
||||
foreach (PanGestureRecognizer recognizer in panGestures)
|
||||
((IPanGestureController)recognizer).SendPanCompleted(view, Application.Current.PanGestureId);
|
||||
Application.Current.PanGestureId++;
|
||||
_isPanning = false;
|
||||
}
|
||||
|
||||
void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
|
||||
{
|
||||
var view = Element as View;
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
HandlePan(e, view);
|
||||
}
|
||||
|
||||
void Touch_FrameReported(object sender, TouchFrameEventArgs e)
|
||||
{
|
||||
_touchPoints = e.GetTouchPoints(Control).Count;
|
||||
}
|
||||
|
||||
void MaybeInvalidate()
|
||||
{
|
||||
if (Element.IsInNativeLayout)
|
||||
return;
|
||||
var parent = (FrameworkElement)Control.Parent;
|
||||
parent?.InvalidateMeasure();
|
||||
Control.InvalidateMeasure();
|
||||
}
|
||||
|
||||
void UpdateInputTransparent()
|
||||
{
|
||||
Control.IsHitTestVisible = !Element.InputTransparent;
|
||||
}
|
||||
|
||||
void UpdateOpacity()
|
||||
{
|
||||
Control.Opacity = Element.Opacity;
|
||||
}
|
||||
|
||||
void UpdateScaleAndTranslateAndRotation()
|
||||
{
|
||||
// TODO : Implement plane projection - Don't exist in WPF framework :(
|
||||
double anchorX = Element.AnchorX;
|
||||
double anchorY = Element.AnchorY;
|
||||
double rotationX = Element.RotationX;
|
||||
double rotationY = Element.RotationY;
|
||||
double rotation = Element.Rotation;
|
||||
double translationX = Element.TranslationX;
|
||||
double translationY = Element.TranslationY;
|
||||
double scale = Element.Scale;
|
||||
|
||||
double offsetX = scale == 0 ? 0 : translationX / scale;
|
||||
double offsetY = scale == 0 ? 0 : translationY / scale;
|
||||
|
||||
Control.RenderTransformOrigin = new System.Windows.Point(anchorX, anchorY);
|
||||
Control.RenderTransform = new TransformGroup()
|
||||
{
|
||||
Children = new TransformCollection()
|
||||
{
|
||||
new ScaleTransform
|
||||
{
|
||||
ScaleX = scale,
|
||||
ScaleY = scale
|
||||
},
|
||||
new TranslateTransform()
|
||||
{
|
||||
X = offsetX,
|
||||
Y = offsetY
|
||||
},
|
||||
new RotateTransform()
|
||||
{
|
||||
|
||||
CenterX = anchorX,
|
||||
CenterY = anchorY,
|
||||
Angle = Element.Rotation,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void UpdateTouchFrameReportedEvent()
|
||||
{
|
||||
if (_touchFrameReportedEventSet)
|
||||
return;
|
||||
|
||||
Touch.FrameReported -= Touch_FrameReported;
|
||||
_touchFrameReportedEventSet = false;
|
||||
|
||||
var view = Element as View;
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
if (!view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Any(g => g.TouchPoints > 1))
|
||||
return;
|
||||
|
||||
Touch.FrameReported += Touch_FrameReported;
|
||||
_touchFrameReportedEventSet = true;
|
||||
}
|
||||
|
||||
void UpdateVisibility()
|
||||
{
|
||||
Control.Visibility = Element.IsVisible ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
_disposed = true;
|
||||
|
||||
if (_control != null)
|
||||
{
|
||||
_control.MouseLeftButtonUp -= MouseLeftButtonUp;
|
||||
_control.ManipulationDelta -= OnManipulationDelta;
|
||||
_control.ManipulationCompleted -= OnManipulationCompleted;
|
||||
}
|
||||
|
||||
if (_element != null)
|
||||
{
|
||||
_element.BatchCommitted -= HandleRedrawNeeded;
|
||||
_element.PropertyChanged -= HandlePropertyChanged;
|
||||
}
|
||||
|
||||
Element = null;
|
||||
Control = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal class WPFDeviceInfo : DeviceInfo
|
||||
{
|
||||
internal const string BWPorientationChangedName = "Xamarin.WPF.OrientationChanged";
|
||||
readonly double _scalingFactor;
|
||||
|
||||
public WPFDeviceInfo()
|
||||
{
|
||||
MessagingCenter.Subscribe(this, BWPorientationChangedName, (FormsApplicationPage page, DeviceOrientation orientation) => { CurrentOrientation = orientation; });
|
||||
|
||||
var content = System.Windows.Application.Current.MainWindow;
|
||||
|
||||
// Scaling Factor for Windows Phone 8 is relative to WVGA: https://msdn.microsoft.com/en-us/library/windows/apps/jj206974(v=vs.105).aspx
|
||||
//_scalingFactor = content.ScaleFactor / 100d;
|
||||
//PixelScreenSize = new Size(content.ActualWidth * _scalingFactor, content.ActualHeight * _scalingFactor);
|
||||
PixelScreenSize = new Size(SystemParameters.PrimaryScreenWidth, SystemParameters.PrimaryScreenHeight);
|
||||
ScaledScreenSize = new Size(SystemParameters.PrimaryScreenWidth, SystemParameters.PrimaryScreenHeight);
|
||||
}
|
||||
|
||||
public override Size PixelScreenSize { get; }
|
||||
|
||||
public override Size ScaledScreenSize { get; }
|
||||
|
||||
public override double ScalingFactor
|
||||
{
|
||||
get { return _scalingFactor; }
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
MessagingCenter.Unsubscribe<FormsApplicationPage, DeviceOrientation>(this, BWPorientationChangedName);
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal sealed class WPFExpressionSearch : IExpressionSearch
|
||||
{
|
||||
List<object> _results;
|
||||
Type _targeType;
|
||||
|
||||
public List<T> FindObjects<T>(Expression expression) where T : class
|
||||
{
|
||||
_results = new List<object>();
|
||||
_targeType = typeof(T);
|
||||
|
||||
Visit(expression);
|
||||
|
||||
List<T> final = _results.Cast<T>().ToList();
|
||||
_results = null;
|
||||
return final;
|
||||
}
|
||||
|
||||
void Visit(Expression expression)
|
||||
{
|
||||
if (expression == null)
|
||||
return;
|
||||
|
||||
switch (expression.NodeType)
|
||||
{
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
case ExpressionType.Not:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
case ExpressionType.ArrayLength:
|
||||
case ExpressionType.Quote:
|
||||
case ExpressionType.TypeAs:
|
||||
case ExpressionType.UnaryPlus:
|
||||
Visit(((UnaryExpression)expression).Operand);
|
||||
break;
|
||||
case ExpressionType.Add:
|
||||
case ExpressionType.AddChecked:
|
||||
case ExpressionType.Subtract:
|
||||
case ExpressionType.SubtractChecked:
|
||||
case ExpressionType.Multiply:
|
||||
case ExpressionType.MultiplyChecked:
|
||||
case ExpressionType.Divide:
|
||||
case ExpressionType.Modulo:
|
||||
case ExpressionType.Power:
|
||||
case ExpressionType.And:
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.Or:
|
||||
case ExpressionType.OrElse:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.Coalesce:
|
||||
case ExpressionType.ArrayIndex:
|
||||
case ExpressionType.RightShift:
|
||||
case ExpressionType.LeftShift:
|
||||
case ExpressionType.ExclusiveOr:
|
||||
var binary = (BinaryExpression)expression;
|
||||
Visit(binary.Left);
|
||||
Visit(binary.Right);
|
||||
Visit(binary.Conversion);
|
||||
break;
|
||||
case ExpressionType.TypeIs:
|
||||
Visit(((TypeBinaryExpression)expression).Expression);
|
||||
break;
|
||||
case ExpressionType.Conditional:
|
||||
var conditional = (ConditionalExpression)expression;
|
||||
Visit(conditional.Test);
|
||||
Visit(conditional.IfTrue);
|
||||
Visit(conditional.IfFalse);
|
||||
break;
|
||||
case ExpressionType.MemberAccess:
|
||||
VisitMemberAccess((MemberExpression)expression);
|
||||
break;
|
||||
case ExpressionType.Call:
|
||||
var methodCall = (MethodCallExpression)expression;
|
||||
Visit(methodCall.Object);
|
||||
VisitList(methodCall.Arguments, Visit);
|
||||
break;
|
||||
case ExpressionType.Lambda:
|
||||
Visit(((LambdaExpression)expression).Body);
|
||||
break;
|
||||
case ExpressionType.New:
|
||||
VisitList(((NewExpression)expression).Arguments, Visit);
|
||||
break;
|
||||
case ExpressionType.NewArrayInit:
|
||||
case ExpressionType.NewArrayBounds:
|
||||
VisitList(((NewArrayExpression)expression).Expressions, Visit);
|
||||
break;
|
||||
case ExpressionType.Invoke:
|
||||
var invocation = (InvocationExpression)expression;
|
||||
VisitList(invocation.Arguments, Visit);
|
||||
Visit(invocation.Expression);
|
||||
break;
|
||||
case ExpressionType.MemberInit:
|
||||
var init = (MemberInitExpression)expression;
|
||||
VisitList(init.NewExpression.Arguments, Visit);
|
||||
VisitList(init.Bindings, VisitBinding);
|
||||
break;
|
||||
case ExpressionType.ListInit:
|
||||
var init1 = (ListInitExpression)expression;
|
||||
VisitList(init1.NewExpression.Arguments, Visit);
|
||||
VisitList(init1.Initializers, initializer => VisitList(initializer.Arguments, Visit));
|
||||
break;
|
||||
case ExpressionType.Constant:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException(string.Format("Unhandled expression type: '{0}'", expression.NodeType));
|
||||
}
|
||||
}
|
||||
|
||||
void VisitBinding(MemberBinding binding)
|
||||
{
|
||||
switch (binding.BindingType)
|
||||
{
|
||||
case MemberBindingType.Assignment:
|
||||
Visit(((MemberAssignment)binding).Expression);
|
||||
break;
|
||||
case MemberBindingType.MemberBinding:
|
||||
VisitList(((MemberMemberBinding)binding).Bindings, VisitBinding);
|
||||
break;
|
||||
case MemberBindingType.ListBinding:
|
||||
VisitList(((MemberListBinding)binding).Initializers, initializer => VisitList(initializer.Arguments, Visit));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException(string.Format("Unhandled binding type '{0}'", binding.BindingType));
|
||||
}
|
||||
}
|
||||
|
||||
static void VisitList<TList>(IEnumerable<TList> list, Action<TList> visitor)
|
||||
{
|
||||
foreach (TList element in list)
|
||||
{
|
||||
visitor(element);
|
||||
}
|
||||
}
|
||||
|
||||
// All important magic happens here
|
||||
void VisitMemberAccess(MemberExpression member)
|
||||
{
|
||||
if (member.Expression is ConstantExpression && member.Member is FieldInfo)
|
||||
{
|
||||
object container = ((ConstantExpression)member.Expression).Value;
|
||||
object value = ((FieldInfo)member.Member).GetValue(container);
|
||||
|
||||
if (_targeType.IsInstanceOfType(value))
|
||||
{
|
||||
_results.Add(value);
|
||||
}
|
||||
}
|
||||
Visit(member.Expression);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.IO.IsolatedStorage;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal class WPFIsolatedStorageFile : IIsolatedStorageFile
|
||||
{
|
||||
readonly IsolatedStorageFile _isolatedStorageFile;
|
||||
|
||||
public WPFIsolatedStorageFile(IsolatedStorageFile isolatedStorageFile)
|
||||
{
|
||||
_isolatedStorageFile = isolatedStorageFile;
|
||||
}
|
||||
|
||||
public Task CreateDirectoryAsync(string path)
|
||||
{
|
||||
_isolatedStorageFile.CreateDirectory(path);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task<bool> GetDirectoryExistsAsync(string path)
|
||||
{
|
||||
return Task.FromResult(_isolatedStorageFile.DirectoryExists(path));
|
||||
}
|
||||
|
||||
public Task<bool> GetFileExistsAsync(string path)
|
||||
{
|
||||
return Task.FromResult(_isolatedStorageFile.FileExists(path));
|
||||
}
|
||||
|
||||
public Task<DateTimeOffset> GetLastWriteTimeAsync(string path)
|
||||
{
|
||||
return Task.FromResult(_isolatedStorageFile.GetLastWriteTime(path));
|
||||
}
|
||||
|
||||
public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access)
|
||||
{
|
||||
Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access);
|
||||
return Task.FromResult(stream);
|
||||
}
|
||||
|
||||
public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, (System.IO.FileShare)share);
|
||||
return Task.FromResult(stream);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.IsolatedStorage;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
public class WPFPlatformServices : IPlatformServices
|
||||
{
|
||||
public bool IsInvokeRequired
|
||||
{
|
||||
get { return !System.Windows.Application.Current.Dispatcher.CheckAccess(); }
|
||||
}
|
||||
|
||||
public string RuntimePlatform => Device.WPF;
|
||||
|
||||
public void OpenUriAction(Uri uri)
|
||||
{
|
||||
//TODO : OpenUriAction
|
||||
}
|
||||
|
||||
public void BeginInvokeOnMainThread(Action action)
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(action);
|
||||
}
|
||||
|
||||
public Ticker CreateTicker()
|
||||
{
|
||||
return new WPFTicker();
|
||||
}
|
||||
|
||||
public Assembly[] GetAssemblies()
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies();
|
||||
}
|
||||
|
||||
public string GetMD5Hash(string input)
|
||||
{
|
||||
// MSDN - Documentation -https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5(v=vs.110).aspx
|
||||
using (MD5 md5Hash = MD5.Create())
|
||||
{
|
||||
// Convert the input string to a byte array and compute the hash.
|
||||
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
|
||||
|
||||
// Create a new Stringbuilder to collect the bytes
|
||||
// and create a string.
|
||||
StringBuilder sBuilder = new StringBuilder();
|
||||
|
||||
// Loop through each byte of the hashed data
|
||||
// and format each one as a hexadecimal string.
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
sBuilder.Append(data[i].ToString("x2"));
|
||||
}
|
||||
|
||||
// Return the hexadecimal string.
|
||||
return sBuilder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case NamedSize.Default:
|
||||
if (typeof(Label).IsAssignableFrom(targetElementType))
|
||||
return (double)System.Windows.Application.Current.Resources["FontSizeNormal"];
|
||||
return (double)System.Windows.Application.Current.Resources["FontSizeMedium"];
|
||||
case NamedSize.Micro:
|
||||
return (double)System.Windows.Application.Current.Resources["FontSizeSmall"] - 3;
|
||||
case NamedSize.Small:
|
||||
return (double)System.Windows.Application.Current.Resources["FontSizeSmall"];
|
||||
case NamedSize.Medium:
|
||||
if (useOldSizes)
|
||||
goto case NamedSize.Default;
|
||||
return (double)System.Windows.Application.Current.Resources["FontSizeMedium"];
|
||||
case NamedSize.Large:
|
||||
return (double)System.Windows.Application.Current.Resources["FontSizeLarge"];
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("size");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<Stream>();
|
||||
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = WebRequest.CreateHttp(uri);
|
||||
request.BeginGetResponse(ar =>
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
tcs.SetCanceled();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Stream stream = request.EndGetResponse(ar).GetResponseStream();
|
||||
tcs.TrySetResult(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public IIsolatedStorageFile GetUserStoreForApplication()
|
||||
{
|
||||
return new WPFIsolatedStorageFile(IsolatedStorageFile.GetUserStoreForAssembly());
|
||||
}
|
||||
|
||||
public void StartTimer(TimeSpan interval, Func<bool> callback)
|
||||
{
|
||||
var timer = new DispatcherTimer { Interval = interval };
|
||||
timer.Start();
|
||||
timer.Tick += (sender, args) =>
|
||||
{
|
||||
bool result = callback();
|
||||
if (!result)
|
||||
timer.Stop();
|
||||
};
|
||||
}
|
||||
|
||||
public void QuitApplication()
|
||||
{
|
||||
System.Windows.Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:wpf="clr-namespace:Xamarin.Forms.Platform.WPF">
|
||||
|
||||
<system:Double x:Key="FontSizeSmall">18</system:Double>
|
||||
<system:Double x:Key="FontSizeNormal">20</system:Double>
|
||||
<system:Double x:Key="FontSizeMedium">22</system:Double>
|
||||
<system:Double x:Key="FontSizeMediumLarge">25</system:Double>
|
||||
<system:Double x:Key="FontSizeLarge">32</system:Double>
|
||||
<system:Double x:Key="FontSizeExtraLarge">42</system:Double>
|
||||
<system:Double x:Key="FontSizeExtraExtraLarge">72</system:Double>
|
||||
<system:Double x:Key="FontSizeHuge">186</system:Double>
|
||||
|
||||
|
||||
<FontFamily x:Key="FontFamilyNormal">Segoe UI</FontFamily>
|
||||
<FontFamily x:Key="FontFamilySemiBold">Segoe UI</FontFamily>
|
||||
|
||||
|
||||
<wpf:HeightConverter x:Key="HeightConverter" />
|
||||
<wpf:ViewToRendererConverter x:Key="ViewToRenderer" />
|
||||
<wpf:CaseConverter x:Key="LowerConverter" ConvertToUpper="False" />
|
||||
<wpf:CaseConverter x:Key="UpperConverter" ConvertToUpper="True" />
|
||||
<wpf:CollapseWhenEmptyConverter x:Key="CollapseWhenEmpty" />
|
||||
<wpf:ColorConverter x:Key="ColorConverter" />
|
||||
<wpf:ImageConverter x:Key="ImageConverter" />
|
||||
|
||||
<Style x:Key="BaseTextBlockStyle" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="FontSize" Value="15"/>
|
||||
<Setter Property="TextTrimming" Value="None"/>
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
<Setter Property="LineStackingStrategy" Value="MaxHeight"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="HeaderTextBlockStyle" TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BaseTextBlockStyle}">
|
||||
<Setter Property="FontSize" Value="46"/>
|
||||
<Setter Property="FontWeight" Value="Light"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SubheaderTextBlockStyle" TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BaseTextBlockStyle}">
|
||||
<Setter Property="FontSize" Value="34"/>
|
||||
<Setter Property="FontWeight" Value="Light"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="BodyTextBlockStyle" TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BaseTextBlockStyle}">
|
||||
<Setter Property="FontWeight" Value="Normal"/>
|
||||
<Setter Property="FontSize" Value="15"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ListViewItemTextBlockStyle" TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BodyTextBlockStyle}">
|
||||
<Setter Property="FontSize" Value="20"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CaptionTextBlockStyle" TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BaseTextBlockStyle}">
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="FontWeight" Value="Normal"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ActionSheetList" TargetType="ListView">
|
||||
<Setter Property="SelectionMode" Value="Single"/>
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="ItemContainerStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="Margin" Value="10,0,0,0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="ItemTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ListViewItemTextBlockStyle}" />
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ListViewTemplate" TargetType="ListView">
|
||||
<Setter Property="SelectionMode" Value="Single"/>
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
|
||||
<Setter Property="ItemContainerStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Height" Value="Auto" />
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TableViewTemplate" TargetType="ListView">
|
||||
<Setter Property="SelectionMode" Value="Single"/>
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="ItemContainerStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="Margin" Value="5,0,0,0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Height" Value="Auto" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListViewItem}">
|
||||
<ContentPresenter />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="CellTemplate">
|
||||
<wpf:CellControl Cell="{Binding}" Margin="5,0,0,0"
|
||||
Height="{Binding Cell.RenderHeight,RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource HeightConverter}}" >
|
||||
</wpf:CellControl>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="TableSectionHeader">
|
||||
<TextBlock Text="{Binding Converter={StaticResource LowerConverter}}" Style="{StaticResource SubheaderTextBlockStyle}"
|
||||
FontSize="24" Foreground="Black" />
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="TextCell">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Text="{Binding Text}"
|
||||
Style="{StaticResource ListViewItemTextBlockStyle}"
|
||||
Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}">
|
||||
|
||||
<TextBlock.Foreground>
|
||||
<MultiBinding Converter="{StaticResource ColorConverter}" ConverterParameter="{x:Static TextBlock.ForegroundProperty}">
|
||||
<Binding RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="TextColor"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Foreground>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Text="{Binding Detail}" Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}">
|
||||
<TextBlock.Foreground>
|
||||
<MultiBinding Converter="{StaticResource ColorConverter}" ConverterParameter="{x:Static TextBlock.ForegroundProperty}">
|
||||
<Binding RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="DetailColor"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Foreground>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="SwitchCell">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="{Binding Text}" Style="{StaticResource ListViewItemTextBlockStyle}" VerticalAlignment="Center" />
|
||||
<CheckBox Grid.Column="1" IsChecked="{Binding On, Mode=TwoWay}" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="ImageCell">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Image Grid.Column="0" Grid.RowSpan="2"
|
||||
Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}"
|
||||
VerticalAlignment="Center" />
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="0"
|
||||
Text="{Binding Text}" Style="{StaticResource ListViewItemTextBlockStyle}"
|
||||
Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}">
|
||||
<TextBlock.Foreground>
|
||||
<MultiBinding Converter="{StaticResource ColorConverter}" ConverterParameter="{x:Static TextBlock.ForegroundProperty}">
|
||||
<Binding RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="TextColor"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Foreground>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="1"
|
||||
Text="{Binding Detail}" Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}">
|
||||
<TextBlock.Foreground>
|
||||
<MultiBinding Converter="{StaticResource ColorConverter}" ConverterParameter="{x:Static TextBlock.ForegroundProperty}">
|
||||
<Binding RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="DetailColor"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Foreground>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="EntryCell">
|
||||
|
||||
<wpf:FormsTextBox Grid.Column="1" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
|
||||
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="ViewCell">
|
||||
<ContentPresenter Content="{Binding View, Converter={StaticResource ViewToRenderer}}" />
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Platform.WPF
|
||||
{
|
||||
internal class WPFTicker : Ticker
|
||||
{
|
||||
readonly DispatcherTimer _timer;
|
||||
|
||||
public WPFTicker()
|
||||
{
|
||||
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(15) };
|
||||
_timer.Tick += (sender, args) => SendSignals();
|
||||
}
|
||||
|
||||
protected override void DisableTimer()
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
protected override void EnableTimer()
|
||||
{
|
||||
_timer.Start();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{140BC260-8B15-4D3A-B1B0-DDD8072918CC}</ProjectGuid>
|
||||
<OutputType>library</OutputType>
|
||||
<RootNamespace>Xamarin.Forms.Platform.WPF</RootNamespace>
|
||||
<AssemblyName>Xamarin.Forms.Platform.WPF</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>6</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>6</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\OpenTK.3.0.0-pre\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK.GLControl, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\OpenTK.GLControl.3.0.0-pre\lib\net20\OpenTK.GLControl.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="WindowsFormsIntegration" />
|
||||
<Reference Include="WpfLightToolkit, Version=1.0.0.27, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WpfLightToolkit.1.0.1\lib\net45\WpfLightToolkit.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Animatable.cs" />
|
||||
<Compile Include="CellControl.cs" />
|
||||
<Compile Include="Converters\CaseConverter.cs" />
|
||||
<Compile Include="Converters\CollapseWhenEmptyConverter.cs" />
|
||||
<Compile Include="Converters\ColorConverter.cs" />
|
||||
<Compile Include="Converters\HeightConverter.cs" />
|
||||
<Compile Include="Converters\ImageConverter.cs" />
|
||||
<Compile Include="Converters\ViewToRendererConverter.cs" />
|
||||
<Compile Include="CustomContextMenu.cs" />
|
||||
<Compile Include="ElementChangedEventArgs.cs" />
|
||||
<Compile Include="ExportRendererAttribute.cs" />
|
||||
<Compile Include="Extensions\AlignmentExtensions.cs" />
|
||||
<Compile Include="Extensions\ColorExtensions.cs" />
|
||||
<Compile Include="Extensions\DeviceExtensions.cs" />
|
||||
<Compile Include="Extensions\FontExtensions.cs" />
|
||||
<Compile Include="Extensions\FormattedStringExtensions.cs" />
|
||||
<Compile Include="Extensions\FrameworkElementExtensions.cs" />
|
||||
<Compile Include="Extensions\ImageExtensions.cs" />
|
||||
<Compile Include="Extensions\KeyboardExtensions.cs" />
|
||||
<Compile Include="Extensions\PageExtensions.cs" />
|
||||
<Compile Include="Extensions\VisualElementExtensions.cs" />
|
||||
<Compile Include="Forms.cs" />
|
||||
<Compile Include="FormsApplicationPage.cs" />
|
||||
<Compile Include="FormsContentLoader.cs" />
|
||||
<Compile Include="FormsPanel.cs" />
|
||||
<Compile Include="FormsTextBox.cs" />
|
||||
<Compile Include="Helpers\UiHelper.cs" />
|
||||
<Compile Include="ICellRenderer.cs" />
|
||||
<Compile Include="IVisualElementRenderer.cs" />
|
||||
<Compile Include="Platform.cs" />
|
||||
<Compile Include="PlatformEffect.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="Renderers\ActivityIndicatorRenderer.cs" />
|
||||
<Compile Include="Renderers\BoxViewRenderer.cs" />
|
||||
<Compile Include="Renderers\ButtonRenderer.cs" />
|
||||
<Compile Include="Renderers\CarouselPageRenderer.cs" />
|
||||
<Compile Include="Renderers\DatePickerRenderer.cs" />
|
||||
<Compile Include="Renderers\EditorRenderer.cs" />
|
||||
<Compile Include="Renderers\EntryRenderer.cs" />
|
||||
<Compile Include="Renderers\FrameRenderer.cs" />
|
||||
<Compile Include="Renderers\ImageRenderer.cs" />
|
||||
<Compile Include="Renderers\LabelRenderer.cs" />
|
||||
<Compile Include="Renderers\LayoutRenderer.cs" />
|
||||
<Compile Include="Renderers\ListViewRenderer.cs" />
|
||||
<Compile Include="Renderers\MasterDetailPageRenderer.cs" />
|
||||
<Compile Include="Renderers\NavigationPageRenderer.cs" />
|
||||
<Compile Include="Renderers\OpenGLViewRenderer.cs" />
|
||||
<Compile Include="Renderers\PageRenderer.cs" />
|
||||
<Compile Include="Renderers\PickerRenderer.cs" />
|
||||
<Compile Include="Renderers\ProgressBarRenderer.cs" />
|
||||
<Compile Include="Renderers\ScrollViewRenderer.cs" />
|
||||
<Compile Include="Renderers\SearchBarRenderer.cs" />
|
||||
<Compile Include="Renderers\SliderRenderer.cs" />
|
||||
<Compile Include="Renderers\StepperRenderer.cs" />
|
||||
<Compile Include="Renderers\SwitchRenderer.cs" />
|
||||
<Compile Include="Renderers\TabbedPageRenderer.cs" />
|
||||
<Compile Include="Renderers\CellRenderer.cs" />
|
||||
<Compile Include="Renderers\TableViewRenderer.cs" />
|
||||
<Compile Include="Renderers\ViewRenderer.cs" />
|
||||
<Compile Include="Renderers\VisualMultiPageRenderer.cs" />
|
||||
<Compile Include="Renderers\VisualPageRenderer.cs" />
|
||||
<Compile Include="Renderers\WebViewRenderer.cs" />
|
||||
<Compile Include="ResourcesProvider.cs" />
|
||||
<Compile Include="VisualElementTracker.cs" />
|
||||
<Compile Include="WPFDeviceInfo.cs" />
|
||||
<Compile Include="WPFExpressionSearch.cs" />
|
||||
<Compile Include="WPFIsolatedStorageFile.cs" />
|
||||
<Compile Include="WPFPlatformServices.cs" />
|
||||
<Compile Include="WPFTicker.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
|
||||
<Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
|
||||
<Name>Xamarin.Forms.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="WPFResources.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="OpenTK" version="3.0.0-pre" targetFramework="net45" />
|
||||
<package id="OpenTK.GLControl" version="3.0.0-pre" targetFramework="net45" />
|
||||
<package id="WpfLightToolkit" version="1.0.1" targetFramework="net461" />
|
||||
</packages>
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27102.0
|
||||
VisualStudioVersion = 15.0.27130.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xamarin.Forms", "Xamarin.Forms", "{9AD757F5-E57A-459D-A0A7-E0675E045B84}"
|
||||
EndProject
|
||||
|
@ -139,6 +139,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Forms.Platform.Tize
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.GTK", "Xamarin.Forms.ControlGallery.GTK\Xamarin.Forms.ControlGallery.GTK.csproj", "{03A51E5B-0A1E-41F0-AAE3-4B19406F7340}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WPF", "Xamarin.Forms.Platform.WPF\Xamarin.Forms.Platform.WPF.csproj", "{140BC260-8B15-4D3A-B1B0-DDD8072918CC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems*{0a39a74b-6f7a-4d41-84f2-b0ccdce899df}*SharedItemsImports = 4
|
||||
|
@ -491,92 +493,6 @@ Global
|
|||
{928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|ARM.ActiveCfg = Debug|ARM
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|Templates.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Ad-Hoc|x86.ActiveCfg = Debug|x86
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|ARM.ActiveCfg = Debug|ARM
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|iPhone.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|Templates.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|x64.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.AppStore|x86.ActiveCfg = Debug|x86
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|Templates.ActiveCfg = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x86.Build.0 = Debug|x86
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|Templates.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|x64.Build.0 = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{517B6AE0-792B-4665-9376-5CA33E539181}.Release|x86.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|ARM.ActiveCfg = Debug|ARM
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|Templates.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Ad-Hoc|x86.ActiveCfg = Debug|x86
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|ARM.ActiveCfg = Debug|ARM
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|iPhone.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|Templates.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|x64.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.AppStore|x86.ActiveCfg = Debug|x86
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Templates.ActiveCfg = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x86.Build.0 = Debug|x86
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|ARM.Deploy.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhone.Deploy.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Templates.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x64.Deploy.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x86.Deploy.0 = Release|Any CPU
|
||||
{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
|
||||
{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
|
||||
|
@ -831,44 +747,6 @@ Global
|
|||
{ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x64.Build.0 = Release|Any CPU
|
||||
{ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|ARM.ActiveCfg = Debug|ARM
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|Templates.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Ad-Hoc|x86.ActiveCfg = Debug|x86
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|ARM.ActiveCfg = Debug|ARM
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|iPhone.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|Templates.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|x64.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.AppStore|x86.ActiveCfg = Debug|x86
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|Templates.ActiveCfg = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x86.Build.0 = Debug|x86
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|Templates.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
|
||||
{BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
|
||||
|
@ -1333,7 +1211,6 @@ Global
|
|||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|ARM.Build.0 = Release|ARM
|
||||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhone.ActiveCfg = Release|ARM
|
||||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhone.Build.0 = Release|ARM
|
||||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhone.Deploy.0 = Release|ARM
|
||||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhoneSimulator.ActiveCfg = Release|x86
|
||||
{AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|Templates.ActiveCfg = Release|x86
|
||||
|
@ -1387,9 +1264,7 @@ Global
|
|||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|Templates.ActiveCfg = Release|Any CPU
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|x64.ActiveCfg = Release|x64
|
||||
{00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -1440,9 +1315,7 @@ Global
|
|||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|Templates.ActiveCfg = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|Templates.Build.0 = Release|Any CPU
|
||||
{04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|x64.ActiveCfg = Release|x64
|
||||
|
@ -2647,6 +2520,58 @@ Global
|
|||
{03A51E5B-0A1E-41F0-AAE3-4B19406F7340}.Release|x64.Build.0 = Release|Any CPU
|
||||
{03A51E5B-0A1E-41F0-AAE3-4B19406F7340}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{03A51E5B-0A1E-41F0-AAE3-4B19406F7340}.Release|x86.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|Templates.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|Templates.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|x64.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Ad-Hoc|x86.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|Any CPU.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|ARM.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|ARM.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|iPhone.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|iPhone.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|Templates.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|Templates.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|x64.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|x64.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|x86.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.AppStore|x86.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|Templates.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|Templates.Build.0 = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|Templates.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|Templates.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|x64.Build.0 = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -2703,6 +2628,7 @@ Global
|
|||
{699C79F6-1D91-4DBF-B817-E8CFFD6263BB} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
|
||||
{83790029-272E-45AF-A41D-E7716684E5B8} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
|
||||
{03A51E5B-0A1E-41F0-AAE3-4B19406F7340} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
|
||||
{140BC260-8B15-4D3A-B1B0-DDD8072918CC} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {650AE971-2F29-46A8-822C-FB4FCDC6A9A0}
|
||||
|
|
|
@ -673,5 +673,20 @@ button.HeightRequest = Device.OnPlatform (20,30,30);
|
|||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="WPF">
|
||||
<MemberSignature Language="C#" Value="public const string WPF;" />
|
||||
<MemberSignature Language="ILAsm" Value=".field public static literal string WPF" />
|
||||
<MemberType>Field</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>System.String</ReturnType>
|
||||
</ReturnValue>
|
||||
<Docs>
|
||||
<summary>To be added.</summary>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
</Members>
|
||||
</Type>
|
||||
|
|
Загрузка…
Ссылка в новой задаче