我在我的 Windows Phone 8.1 WINRT 应用程序中 添加了一个DrawerLayout Nuget 包。https://www.nuget.org/packages/DrawerLayout/
教程: https ://code.msdn.microsoft.com/windowsapps/WindowsPhone-81-Now-its-b63049f9
所以在添加引用之后,我编写了代码。点击hunberger按钮打开抽屉/列表并再次点击它再次关闭它。它工作正常,但有时应用程序崩溃。我尝试在每个语句上使用断点,但它没有帮助。于是我得到了这个DrawerLayout的源代码(DrawerLayout.cs)。在这个cs文件中有:
try
{
_mainFragment = Children.OfType<Grid>().FirstOrDefault();
_listFragment = Children.OfType<Grid>().ElementAt(1);
}
但它说UIElementCollection不包含OfType的任何定义。我检查了 MSDN 文档: https ://msdn.microsoft.com/en-us/library/system.windows.controls.uielementcollection(v=vs.110).aspx
它在扩展方法中显示OfType 。如何使用这个 OfType?有替代品吗?
DrawerLayout.cs 的完整代码:
using System;
using System.Collections.Generic;
using System.Text;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
namespace DrawerLayout
{
public class DrawerLayout : Grid
{
#region Globals and events
private readonly PropertyPath _translatePath = new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)");
private readonly PropertyPath _colorPath = new PropertyPath("(Grid.Background).(SolidColorBrush.Color)");
private readonly TranslateTransform _listFragmentTransform = new TranslateTransform();
private readonly TranslateTransform _deltaTransform = new TranslateTransform();
private const int MaxAlpha = 100;
public delegate void DrawerEventHandler(object sender);
public event DrawerEventHandler DrawerOpened;
public event DrawerEventHandler DrawerClosed;
private Storyboard _fadeInStoryboard;
private Storyboard _fadeOutStoryboard;
private Grid _listFragment;
private Grid _mainFragment;
private Grid _shadowFragment;
#endregion
#region Dependency Properties
public bool IsDrawerOpen
{
get { return (bool)GetValue(IsDrawerOpenProperty); }
set { SetValue(IsDrawerOpenProperty, value); }
}
public static readonly DependencyProperty IsDrawerOpenProperty = DependencyProperty.Register("IsDrawerOpen", typeof(bool), typeof(DrawerLayout), new PropertyMetadata(false));
private PropertyPath TranslatePath
{
get { return _translatePath; }
}
private PropertyPath ColorPath
{
get { return _colorPath; }
}
#endregion
#region Methods
public DrawerLayout()
{
IsDrawerOpen = false;
}
public void InitializeDrawerLayout()
{
if (Children == null) return;
if (Children.Count < 2) return;
try
{
_mainFragment = Children.OfType<Grid>().FirstOrDefault();
_listFragment = Children.OfType<Grid>().ElementAt(1);
}
catch
{
return;
}
if (_mainFragment == null || _listFragment == null) return;
_mainFragment.Name = "_mainFragment";
_listFragment.Name = "_listFragment";
// _mainFragment
_mainFragment.HorizontalAlignment = HorizontalAlignment.Stretch;
_mainFragment.VerticalAlignment = VerticalAlignment.Stretch;
if (_mainFragment.Background == null) _mainFragment.Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));
// Render transform _listFragment
_listFragment.HorizontalAlignment = HorizontalAlignment.Left;
_listFragment.VerticalAlignment = VerticalAlignment.Stretch;
_listFragment.Width = (Window.Current.Bounds.Width/3)*2;
if (_listFragment.Background == null) _listFragment.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
var animatedTranslateTransform = new TranslateTransform {X = -_listFragment.Width, Y = 0};
_listFragment.RenderTransform = animatedTranslateTransform;
_listFragment.RenderTransformOrigin = new Point(0.5, 0.5);
_listFragment.UpdateLayout();
// Create a shadow element
_shadowFragment = new Grid
{
Name = "_shadowFragment",
Background = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255)),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Visibility = Visibility.Collapsed
};
_shadowFragment.Tapped += shadowFragment_Tapped;
_shadowFragment.IsHitTestVisible = false;
// Set ZIndexes
Canvas.SetZIndex(_shadowFragment, 50);
Canvas.SetZIndex(_listFragment, 51);
Children.Add(_shadowFragment);
// Create a new fadeIn animation storyboard
_fadeInStoryboard = new Storyboard();
// New double animation
var doubleAnimation1 = new DoubleAnimation {Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)), To = 0};
Storyboard.SetTarget(doubleAnimation1, _listFragment);
Storyboard.SetTargetProperty(doubleAnimation1, TranslatePath.Path);
_fadeInStoryboard.Children.Add(doubleAnimation1);
// New color animation for _shadowFragment
var colorAnimation1 = new ColorAnimation
{
Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
To = Color.FromArgb(190, 0, 0, 0)
};
Storyboard.SetTarget(colorAnimation1, _shadowFragment);
Storyboard.SetTargetProperty(colorAnimation1,ColorPath.Path);
_fadeInStoryboard.Children.Add(colorAnimation1);
// Create a new fadeOut animation storyboard
_fadeOutStoryboard = new Storyboard();
// New double animation
var doubleAnimation2 = new DoubleAnimation
{
Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
To = -_listFragment.Width
};
Storyboard.SetTarget(doubleAnimation2, _listFragment);
Storyboard.SetTargetProperty(doubleAnimation2, TranslatePath.Path);
_fadeOutStoryboard.Children.Add(doubleAnimation2);
// New color animation for _shadowFragment
var colorAnimation2 = new ColorAnimation
{
Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
To = Color.FromArgb(0, 0, 0, 0)
};
Storyboard.SetTarget(colorAnimation2, _shadowFragment);
Storyboard.SetTargetProperty(colorAnimation2, ColorPath.Path);
_fadeOutStoryboard.Children.Add(colorAnimation2);
_mainFragment.ManipulationMode = ManipulationModes.All;
_mainFragment.ManipulationStarted += mainFragment_ManipulationStarted;
_listFragment.ManipulationMode = ManipulationModes.All;
_listFragment.ManipulationStarted += listFragment_ManipulationStarted;
}
public void OpenDrawer()
{
if (_fadeInStoryboard == null || _mainFragment == null || _listFragment == null) return;
_shadowFragment.Visibility = Visibility.Visible;
_shadowFragment.IsHitTestVisible = true;
_shadowFragment.Background = new SolidColorBrush(Color.FromArgb(MaxAlpha, 0, 0, 0));
_fadeInStoryboard.Begin();
IsDrawerOpen = true;
if (DrawerOpened != null)
DrawerOpened(this);
}
public void CloseDrawer()
{
if (_fadeOutStoryboard == null || _mainFragment == null || _listFragment == null) return;
_fadeOutStoryboard.Begin();
_fadeOutStoryboard.Completed += fadeOutStoryboard_Completed;
IsDrawerOpen = false;
if (DrawerClosed != null)
DrawerClosed(this);
}
private void shadowFragment_Tapped(object sender, TappedRoutedEventArgs e)
{
var shadow = new Storyboard();
var doubleAnimation = new DoubleAnimation
{
Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
To = -_listFragment.Width
};
Storyboard.SetTarget(doubleAnimation, _listFragment);
Storyboard.SetTargetProperty(doubleAnimation, TranslatePath.Path);
shadow.Children.Add(doubleAnimation);
var colorAnimation = new ColorAnimation
{
Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
To = Color.FromArgb(0, 0, 0, 0)
};
Storyboard.SetTarget(colorAnimation, _shadowFragment);
Storyboard.SetTargetProperty(colorAnimation, ColorPath.Path);
shadow.Children.Add(colorAnimation);
shadow.Completed += shadow_Completed;
shadow.Begin();
}
private void shadow_Completed(object sender, object e)
{
_shadowFragment.IsHitTestVisible = false;
_shadowFragment.Visibility = Visibility.Collapsed;
this.IsDrawerOpen = false;
// raise close event
if (DrawerClosed != null) DrawerClosed(this);
}
private void fadeOutStoryboard_Completed(object sender, object e)
{
_shadowFragment.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
_shadowFragment.Visibility = Visibility.Collapsed;
if (DrawerClosed != null) DrawerClosed(this);
}
private void MoveListFragment(double left, Color color)
{
var s = new Storyboard();
var doubleAnimation = new DoubleAnimation
{
Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
To = left
};
Storyboard.SetTarget(doubleAnimation, _listFragment);
Storyboard.SetTargetProperty(doubleAnimation, TranslatePath.Path);
s.Children.Add(doubleAnimation);
var colorAnimation = new ColorAnimation { Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)), To = color };
Storyboard.SetTarget(colorAnimation, _shadowFragment);
Storyboard.SetTargetProperty(colorAnimation, ColorPath.Path);
s.Children.Add(colorAnimation);
s.Begin();
}
private void MoveShadowFragment(double left)
{
// Show shadow fragment
_shadowFragment.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
_shadowFragment.Visibility = Visibility.Visible;
// Set bg color based on current _listFragment position.
var maxLeft = _listFragment.ActualWidth;
var currentLeft = maxLeft - left;
var temp = Convert.ToInt32((currentLeft / maxLeft) * MaxAlpha);
// Limit temp variable to 190 to avoid OverflowException
if (temp > MaxAlpha) temp = MaxAlpha;
byte alphaColorIndex;
try
{
alphaColorIndex = Convert.ToByte(MaxAlpha - temp);
}
catch
{
alphaColorIndex = 0;
}
_shadowFragment.Background = new SolidColorBrush(Color.FromArgb(alphaColorIndex, 0, 0, 0));
}
#endregion
#region List Fragment manipulation events
private void listFragment_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
var listWidth = _listFragment.Width;
if (!(e.Position.X >= listWidth - 100) || !(e.Position.X < listWidth)) return;
_listFragment.ManipulationDelta += listFragment_ManipulationDelta;
_listFragment.ManipulationCompleted += listFragment_ManipulationCompleted;
}
private void listFragment_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (Math.Abs(e.Cumulative.Translation.X) < 0) return;
if (e.Cumulative.Translation.X <= -_listFragment.Width || e.Cumulative.Translation.X > 0)
{
listFragment_ManipulationCompleted(this, null);
return;
}
_listFragmentTransform.X = e.Cumulative.Translation.X;
_listFragment.RenderTransform = _listFragmentTransform;
MoveShadowFragment(e.Cumulative.Translation.X + _listFragment.Width);
}
private void listFragment_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
// Get left of _listFragment
var transform = (TranslateTransform)_listFragment.RenderTransform;
if (transform == null) return;
var left = transform.X;
// Set snap divider to 1/3 of _mainFragment width
var snapLimit = _mainFragment.ActualWidth / 3;
// Get init position of _listFragment
const int initialPosition = 0;
// If current left coordinate is smaller than snap limit, close drawer
if (Math.Abs(initialPosition - left) > snapLimit)
{
MoveListFragment(-_listFragment.Width, Color.FromArgb(0, 0, 0, 0));
_shadowFragment.Visibility = Visibility.Collapsed;
_shadowFragment.IsHitTestVisible = false;
_listFragment.ManipulationDelta -= listFragment_ManipulationDelta;
_listFragment.ManipulationCompleted -= listFragment_ManipulationCompleted;
IsDrawerOpen = false;
// raise DrawerClosed event
if (DrawerClosed != null) DrawerClosed(this);
}
// else open drawer
else if (Math.Abs(initialPosition - left) < snapLimit)
{
// move drawer to zero
MoveListFragment(0, Color.FromArgb(190, 0, 0, 0));
_shadowFragment.Visibility = Visibility.Visible;
_shadowFragment.IsHitTestVisible = true;
_listFragment.ManipulationDelta -= listFragment_ManipulationDelta;
_listFragment.ManipulationCompleted -= listFragment_ManipulationCompleted;
IsDrawerOpen = true;
// raise Drawer_Open event
if (DrawerOpened != null) DrawerOpened(this);
}
}
#endregion
#region Main fragment manipulation events
private void mainFragment_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
// If the user has the first touch on the left side of canvas, that means he's trying to swipe the drawer
if (!(e.Position.X <= 40)) return;
// Manipulation can be allowed
_mainFragment.ManipulationDelta += mainFragment_ManipulationDelta;
_mainFragment.ManipulationCompleted += mainFragment_ManipulationCompleted;
}
private void mainFragment_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (Math.Abs(e.Cumulative.Translation.X) < 0) return;
if (e.Cumulative.Translation.X >= _listFragment.Width)
{
mainFragment_ManipulationCompleted(this, null);
return;
}
_deltaTransform.X = -_listFragment.Width + e.Cumulative.Translation.X;
_listFragment.RenderTransform = _deltaTransform;
MoveShadowFragment(e.Cumulative.Translation.X);
}
private void mainFragment_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
// Get left of _listFragment
var transform = (TranslateTransform)_listFragment.RenderTransform;
if (transform == null) return;
var left = transform.X;
// Set snap divider to 1/3 of _mainFragment width
var snapLimit = _mainFragment.ActualWidth / 3;
// Get init position of _listFragment
var initialPosition = -_listFragment.Width;
// If current left coordinate is smaller than snap limit, close drawer
if (Math.Abs(initialPosition - left) < snapLimit)
{
MoveListFragment(initialPosition, Color.FromArgb(0, 0, 0, 0));
_shadowFragment.Visibility = Visibility.Collapsed;
_shadowFragment.IsHitTestVisible = false;
_mainFragment.ManipulationDelta -= mainFragment_ManipulationDelta;
_mainFragment.ManipulationCompleted -= mainFragment_ManipulationCompleted;
IsDrawerOpen = false;
// raise DrawerClosed event
if (DrawerClosed != null) DrawerClosed(this);
}
// else open drawer
else if (Math.Abs(initialPosition - left) > snapLimit)
{
// move drawer to zero
MoveListFragment(0, Color.FromArgb(190, 0, 0, 0));
_shadowFragment.Visibility = Visibility.Visible;
_shadowFragment.IsHitTestVisible = true;
_mainFragment.ManipulationDelta -= mainFragment_ManipulationDelta;
_mainFragment.ManipulationCompleted -= mainFragment_ManipulationCompleted;
IsDrawerOpen = true;
// raise DrawerClosed event
if (DrawerOpened != null) DrawerOpened(this);
}
}
#endregion
}
}
调用 InitializeDrawerLayout:
public PageConstructor()
{
this.InitializeComponent();
this.Loaded += PageConstructor_Loaded;
this.NavigationCacheMode = NavigationCacheMode.Disabled;
}
void PageConstructor_Loaded()
{
InitializeDrawer();
}
private void InitializeDrawer()
{
DrawerLayout.InitializeDrawerLayout();
//string[] menuItems = new string[5] { "Item1", "Item2", "Item3", "Item4", "Item5" };
//ListMenuItems.ItemsSource = menuItems.ToList();
ListPickerDataClassObject.ListPicker_DrawerListPicker_UserRegistrationPage();
ListMenuItems.ItemsSource = ListPickerDataClassObject.DrawerListObject;
}