[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:
Mohamed CHOUCHANE 2017-12-06 22:15:13 +01:00 коммит произвёл Rui Marinho
Родитель 6d89f8429e
Коммит 1bbd9dfa52
80 изменённых файлов: 7222 добавлений и 130 удалений

Просмотреть файл

@ -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))]

63
Xamarin.Forms.Platform.WPF/Properties/Resources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -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>

26
Xamarin.Forms.Platform.WPF/Properties/Settings.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -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>