关闭包含 UserControl 的 Flyout
Close Flyout which contains a UserControl
我正在为 TextBox 构建用户控件,因为我希望它有一些特殊的行为。
该控件可以在多种上下文中使用,包括作为按钮的弹出按钮。当它是弹出窗口时,我想在用户在编辑文本时按下 Enter 键时关闭弹出窗口。
为实现这一点,该控件有一个 ParentButton
依赖项 属性,如果设置了该依赖项,则会将按钮与弹出按钮一起存储,父页面的 XAML 将其设置在这个案例。该控件有一个 KeyUp
处理程序,它检测 Enter 键,如果设置了 ParentButton
属性,则关闭其弹出窗口。
TextBoxUC.xaml
<UserControl
x:Class="TextBoxUCDemo.TextBoxUC"
...
xmlns:local="using:TextBoxUCDemo"
...>
<StackPanel Width="250">
<TextBox KeyUp="TextBox_KeyUp" Text="Hello" />
</StackPanel>
TextBoxUC.xaml.cs
public sealed partial class TextBoxUC : UserControl
{
public TextBoxUC() {
this.InitializeComponent();
}
internal static readonly DependencyProperty ParentButtonProperty =
DependencyProperty.Register("ParentButton", typeof(Button), typeof(TextBoxUC), new PropertyMetadata(null));
public Button ParentButton {
get { return ((Button)GetValue(ParentButtonProperty)); }
set { SetValue(ParentButtonProperty, value); }
}
private void TextBox_KeyUp(object sender, KeyRoutedEventArgs e) {
switch (e.Key) {
case VirtualKey.Enter:
// (Do something with the Text...)
// If this is a flyout from a button then hide the flyout.
if (ParentButton != null) { // Always null!
ParentButton.Flyout.Hide();
}
break;
default: return;
}
}
}
MainPage.xaml
<Page
x:Class="TextBoxUCDemo.MainPage"
...
xmlns:local="using:TextBoxUCDemo"
...>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="200,300">
<Button Name="flyoutTextBoxButton" Content="Edit">
<Button.Flyout>
<Flyout>
<local:TextBoxUC ParentButton="{Binding ElementName=flyoutTextBoxButton, Path=.}"/>
</Flyout>
</Button.Flyout>
</Button>
</Grid>
问题是 ParentButton 始终为空。
-- 编辑--
我已将问题缩小到绑定到 XAML 中的元素。如果我从 MainPage 的代码隐藏中设置 ParentButton,那么它就可以工作。
在'MainPage.xaml'中:
Loaded="Page_Loaded"
....
<local:TextBoxUC/>
在MainPage.xaml.cs
private void Page_Loaded(object sender, RoutedEventArgs e) {
textBoxUC.ParentButton = this.flyoutTextBoxButton;
}
效果:
if (ParentButton != null) {
// Reaches here
}
所以:问题出在xaml ParentButton="{Binding ElementName=flyoutTextBoxButton, Path=.}"
,它编译但没有效果。
如果我将更改的事件处理程序添加到依赖项 属性 的注册中,则当从代码隐藏设置 ParentButton 时会调用该处理程序,但不会调用绑定到 ElementName。处理程序似乎只对调试有用。我看不出 属性 工作需要它。
您正在将其作为依赖项 属性。这是第一个正确的开始。但在您处理更改的事件之前,您不会真正从中获得任何价值。
我在这里讨论更多:
http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html
祝你好运!
您可以将包含 lambda 表达式的 Action 类型的法线 属性 添加到控件中。
您将在创建控件时设置此 属性,然后在 EnterPressed 事件上在您的控件内调用它。
public class MyControll
{
public Action ActionAfterEnterPressed {get; set;}
private void HandleOnEnterPressed()
{
if(ActionAfterEnterPressed != null)
{
ActionAfterEnterPressed.Invoke();
}
}
}
创建控件的地方
...
MyControl c = new MyControl()
c.ActionAfterEnterPressed = CloseFlyuot;
....
private void CloseFlyuot()
{
_myFlyout.IsOpen = false;
}
通过这种方式,您可以设置任何操作并在需要时从您的控件内部调用它,而无需理会操作实际执行的操作。
祝你好运。
好的,这个怎么样?我过去用过它。工作正常。
[Microsoft.Xaml.Interactivity.TypeConstraint(typeof(Windows.UI.Xaml.Controls.TextBox))]
public class CloseFlyoutOnEnterBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public void Attach(DependencyObject obj)
{
this.AssociatedObject = obj;
(obj as TextBox).KeyUp += TextBox_KeyUp;
}
void TextBox_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (!e.Key.Equals(Windows.System.VirtualKey.Enter))
return;
var parent = this.AssociatedObject;
while (parent != null)
{
if (parent is FlyoutPresenter)
{
((parent as FlyoutPresenter).Parent as Popup).IsOpen = false;
return;
}
else
{
parent = VisualTreeHelper.GetParent(parent);
}
}
}
public void Detach()
{
(this.AssociatedObject as TextBox).KeyUp -= TextBox_KeyUp;
}
}
这样使用:
<Button HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="Click Me">
<Button.Flyout>
<Flyout Placement="Bottom">
<TextBox Width="200"
Header="Name"
PlaceholderText="Jerry Nixon">
<Interactivity:Interaction.Behaviors>
<local:CloseFlyoutOnEnterBehavior />
</Interactivity:Interaction.Behaviors>
</TextBox>
</Flyout>
</Button.Flyout>
</Button>
在此处了解有关行为的更多信息:
http://blog.jerrynixon.com/2013/10/everything-i-know-about-behaviors-in.html
这里(第 3 课):
http://blog.jerrynixon.com/2014/01/the-most-comprehensive-blend-for-visual.html
祝你好运!
我正在为 TextBox 构建用户控件,因为我希望它有一些特殊的行为。
该控件可以在多种上下文中使用,包括作为按钮的弹出按钮。当它是弹出窗口时,我想在用户在编辑文本时按下 Enter 键时关闭弹出窗口。
为实现这一点,该控件有一个 ParentButton
依赖项 属性,如果设置了该依赖项,则会将按钮与弹出按钮一起存储,父页面的 XAML 将其设置在这个案例。该控件有一个 KeyUp
处理程序,它检测 Enter 键,如果设置了 ParentButton
属性,则关闭其弹出窗口。
TextBoxUC.xaml
<UserControl
x:Class="TextBoxUCDemo.TextBoxUC"
...
xmlns:local="using:TextBoxUCDemo"
...>
<StackPanel Width="250">
<TextBox KeyUp="TextBox_KeyUp" Text="Hello" />
</StackPanel>
TextBoxUC.xaml.cs
public sealed partial class TextBoxUC : UserControl
{
public TextBoxUC() {
this.InitializeComponent();
}
internal static readonly DependencyProperty ParentButtonProperty =
DependencyProperty.Register("ParentButton", typeof(Button), typeof(TextBoxUC), new PropertyMetadata(null));
public Button ParentButton {
get { return ((Button)GetValue(ParentButtonProperty)); }
set { SetValue(ParentButtonProperty, value); }
}
private void TextBox_KeyUp(object sender, KeyRoutedEventArgs e) {
switch (e.Key) {
case VirtualKey.Enter:
// (Do something with the Text...)
// If this is a flyout from a button then hide the flyout.
if (ParentButton != null) { // Always null!
ParentButton.Flyout.Hide();
}
break;
default: return;
}
}
}
MainPage.xaml
<Page
x:Class="TextBoxUCDemo.MainPage"
...
xmlns:local="using:TextBoxUCDemo"
...>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="200,300">
<Button Name="flyoutTextBoxButton" Content="Edit">
<Button.Flyout>
<Flyout>
<local:TextBoxUC ParentButton="{Binding ElementName=flyoutTextBoxButton, Path=.}"/>
</Flyout>
</Button.Flyout>
</Button>
</Grid>
问题是 ParentButton 始终为空。
-- 编辑--
我已将问题缩小到绑定到 XAML 中的元素。如果我从 MainPage 的代码隐藏中设置 ParentButton,那么它就可以工作。
在'MainPage.xaml'中:
Loaded="Page_Loaded"
....
<local:TextBoxUC/>
在MainPage.xaml.cs
private void Page_Loaded(object sender, RoutedEventArgs e) {
textBoxUC.ParentButton = this.flyoutTextBoxButton;
}
效果:
if (ParentButton != null) {
// Reaches here
}
所以:问题出在xaml ParentButton="{Binding ElementName=flyoutTextBoxButton, Path=.}"
,它编译但没有效果。
如果我将更改的事件处理程序添加到依赖项 属性 的注册中,则当从代码隐藏设置 ParentButton 时会调用该处理程序,但不会调用绑定到 ElementName。处理程序似乎只对调试有用。我看不出 属性 工作需要它。
您正在将其作为依赖项 属性。这是第一个正确的开始。但在您处理更改的事件之前,您不会真正从中获得任何价值。
我在这里讨论更多:
http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html
祝你好运!
您可以将包含 lambda 表达式的 Action 类型的法线 属性 添加到控件中。 您将在创建控件时设置此 属性,然后在 EnterPressed 事件上在您的控件内调用它。
public class MyControll
{
public Action ActionAfterEnterPressed {get; set;}
private void HandleOnEnterPressed()
{
if(ActionAfterEnterPressed != null)
{
ActionAfterEnterPressed.Invoke();
}
}
}
创建控件的地方
...
MyControl c = new MyControl()
c.ActionAfterEnterPressed = CloseFlyuot;
....
private void CloseFlyuot()
{
_myFlyout.IsOpen = false;
}
通过这种方式,您可以设置任何操作并在需要时从您的控件内部调用它,而无需理会操作实际执行的操作。 祝你好运。
好的,这个怎么样?我过去用过它。工作正常。
[Microsoft.Xaml.Interactivity.TypeConstraint(typeof(Windows.UI.Xaml.Controls.TextBox))]
public class CloseFlyoutOnEnterBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public void Attach(DependencyObject obj)
{
this.AssociatedObject = obj;
(obj as TextBox).KeyUp += TextBox_KeyUp;
}
void TextBox_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (!e.Key.Equals(Windows.System.VirtualKey.Enter))
return;
var parent = this.AssociatedObject;
while (parent != null)
{
if (parent is FlyoutPresenter)
{
((parent as FlyoutPresenter).Parent as Popup).IsOpen = false;
return;
}
else
{
parent = VisualTreeHelper.GetParent(parent);
}
}
}
public void Detach()
{
(this.AssociatedObject as TextBox).KeyUp -= TextBox_KeyUp;
}
}
这样使用:
<Button HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="Click Me">
<Button.Flyout>
<Flyout Placement="Bottom">
<TextBox Width="200"
Header="Name"
PlaceholderText="Jerry Nixon">
<Interactivity:Interaction.Behaviors>
<local:CloseFlyoutOnEnterBehavior />
</Interactivity:Interaction.Behaviors>
</TextBox>
</Flyout>
</Button.Flyout>
</Button>
在此处了解有关行为的更多信息:
http://blog.jerrynixon.com/2013/10/everything-i-know-about-behaviors-in.html
这里(第 3 课):
http://blog.jerrynixon.com/2014/01/the-most-comprehensive-blend-for-visual.html
祝你好运!