C# 单击以编辑控件LostFocus事件问题
我正在开发一个简单的自定义控件,双击该控件可以进入编辑模式 这个概念是基于这个问题 双击时,它会在“编辑模板”上更改初始模板 这似乎很清楚,除了第(5)部分,当控件失去焦点时如何更改模板 仅当包含的控件失去焦点时,才会触发失去焦点事件 下面是一篇关于它的文章 我试图实现相同的技术,但仍然没有结果,当我在控件外单击时,我无法使LostFocus事件为我工作 我的问题在哪里 我的XAMLC# 单击以编辑控件LostFocus事件问题,c#,silverlight,custom-controls,C#,Silverlight,Custom Controls,我正在开发一个简单的自定义控件,双击该控件可以进入编辑模式 这个概念是基于这个问题 双击时,它会在“编辑模板”上更改初始模板 这似乎很清楚,除了第(5)部分,当控件失去焦点时如何更改模板 仅当包含的控件失去焦点时,才会触发失去焦点事件 下面是一篇关于它的文章 我试图实现相同的技术,但仍然没有结果,当我在控件外单击时,我无法使LostFocus事件为我工作 我的问题在哪里 我的XAML 有几个问题。让我们看看 当您在控制之外单击时,为什么没有得到LostFocus事件 我不久前也成为这个错误假
有几个问题。让我们看看 当您在控制之外单击时,为什么没有得到LostFocus事件 我不久前也成为这个错误假设的牺牲品。单击外部不会更改焦点,除非单击一个控件,该控件在单击时显式地将焦点设置为自身(如文本框或各种按钮)。 按Tab键将键盘焦点导航到下一个控件,并查看是否引发事件 但让我们谈谈其他问题:
ControlTemplate x:Key=“DisplayTemplate”
和ControlTemplate x:Key=“EditTemplate”
不建议以这种方式使用ControlTemplates
。而是使用DataTemplate
和相应的ContentPresenters
TimeCodeControl:ContentControl
和x:Class=“Splan\u RiaBusinessApplication.Controls.TimeCodeControl”
是的,我知道这是可能的,但不是真的有用。让我解释一下:
您可以编写自己的专用单击编辑控件作为一次性工具:使用硬编码显示模板和编辑模板编辑TimeCode
和TimeDetail
数据(基本上就是您所做的)。但是,您没有机会使用它并指定另一对模板来允许编辑其他数据类型。
因此,从ContentControl派生没有多大意义,您也可以从UserControl派生
另一种方法是:将单击编辑控件作为一个通用的可重用控件编写,该控件提供两个公共属性:DisplayTemplate和EditTemplate。不要对您的DataContext做任何假设。同样,将ContentControl作为父类没有任何好处。
我建议您从Control
派生,添加两个DataTemplate
类型的dependencProperties
,如前所述,定义一个包含一个或两个ContentPresenter的默认ControlTemplate。在控制代码中,您需要处理MouseLeftButtonDown和LostFocus,并相应地更新布尔标志
以下是一个工作示例:
…确定焦点的扩展方法:
public static class ControlExtensions
{
public static bool IsFocused( this UIElement control )
{
DependencyObject parent;
for (DependencyObject potentialSubControl = FocusManager.GetFocusedElement() as DependencyObject; potentialSubControl != null; potentialSubControl = parent)
{
if (object.ReferenceEquals( potentialSubControl, control ))
{
return true;
}
parent = VisualTreeHelper.GetParent( potentialSubControl );
if (parent == null)
{
FrameworkElement element = potentialSubControl as FrameworkElement;
if (element != null)
{
parent = element.Parent;
}
}
}
return false;
}
}
…还有一个很好的自定义控件:
public class ClickToEditControl : Control
{
public ClickToEditControl()
{
DefaultStyleKey = typeof (ClickToEditControl);
MouseLeftButtonDown += OnMouseLeftButtonDown;
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount==2)
{
GotoEditMode();
e.Handled = true;
}
}
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
if (!this.IsFocused())
GotoDisplayMode();
}
private void GotoDisplayMode()
{
IsInEditMode = false;
}
private void GotoEditMode()
{
IsInEditMode = true;
}
public DataTemplate EditTemplate
{
get { return (DataTemplate) GetValue( EditTemplateProperty ); }
set { SetValue( EditTemplateProperty, value ); }
}
public static readonly DependencyProperty EditTemplateProperty =
DependencyProperty.Register( "EditTemplate", typeof( DataTemplate ), typeof( ClickToEditControl ), null );
public DataTemplate DisplayTemplate
{
get { return (DataTemplate) GetValue( DisplayTemplateProperty ); }
set { SetValue( DisplayTemplateProperty, value ); }
}
public static readonly DependencyProperty DisplayTemplateProperty =
DependencyProperty.Register( "DisplayTemplate", typeof( DataTemplate ), typeof( ClickToEditControl ), null );
public bool IsInEditMode
{
get { return (bool) GetValue( IsInEditModeProperty ); }
set { SetValue( IsInEditModeProperty, value ); }
}
public static readonly DependencyProperty IsInEditModeProperty =
DependencyProperty.Register( "IsInEditMode", typeof( bool ), typeof( ClickToEditControl ), null );
}
…和控制模板:
<clickToEdit:BoolToVisibilityConverter x:Key="VisibleIfInEditMode"/>
<clickToEdit:BoolToVisibilityConverter x:Key="CollapsedIfInEditMode" VisibleIfTrue="False"/>
<Style TargetType="clickToEdit:ClickToEditControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="clickToEdit:ClickToEditControl">
<Grid>
<ContentPresenter
ContentTemplate="{TemplateBinding EditTemplate}"
Content="{Binding}"
Visibility="{Binding IsInEditMode, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource VisibleIfInEditMode}}"/>
<ContentPresenter
ContentTemplate="{TemplateBinding DisplayTemplate}"
Content="{Binding}"
Visibility="{Binding IsInEditMode, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource CollapsedIfInEditMode}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用法:
<clickToEdit:ClickToEditControl Height="20" Width="200">
<clickToEdit:ClickToEditControl.DisplayTemplate>
<DataTemplate>
<TextBlock Text="{Binding MyText}"/>
</DataTemplate>
</clickToEdit:ClickToEditControl.DisplayTemplate>
<clickToEdit:ClickToEditControl.EditTemplate>
<DataTemplate>
<TextBox Text="{Binding MyText, Mode=TwoWay}"/>
</DataTemplate>
</clickToEdit:ClickToEditControl.EditTemplate>
</clickToEdit:ClickToEditControl>
您的IsFocused
检查错误,即使子控件具有焦点,它也将产生false。查看我的更新帖子,了解一种很好的扩展方法
,以检查任何控件
。非常感谢这个很好的解决方案,它很有效,并且从您的代码中可以学到很多东西。我在MouseLeftButtonDown(对象发送者,MouseButtonEventArgs e)上做了一个小的修复私有void{if(e.ClickCount==2){GotoEditMode();this.Focus();e.Handled=true;}}}当你有时间时,请看一下我在“更新”部分的问题文本中发布的解决方案,并让我知道您的想法。
<clickToEdit:ClickToEditControl Height="20" Width="200">
<clickToEdit:ClickToEditControl.DisplayTemplate>
<DataTemplate>
<TextBlock Text="{Binding MyText}"/>
</DataTemplate>
</clickToEdit:ClickToEditControl.DisplayTemplate>
<clickToEdit:ClickToEditControl.EditTemplate>
<DataTemplate>
<TextBox Text="{Binding MyText, Mode=TwoWay}"/>
</DataTemplate>
</clickToEdit:ClickToEditControl.EditTemplate>
</clickToEdit:ClickToEditControl>