Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单击以编辑控件LostFocus事件问题_C#_Silverlight_Custom Controls - Fatal编程技术网

C# 单击以编辑控件LostFocus事件问题

C# 单击以编辑控件LostFocus事件问题,c#,silverlight,custom-controls,C#,Silverlight,Custom Controls,我正在开发一个简单的自定义控件,双击该控件可以进入编辑模式 这个概念是基于这个问题 双击时,它会在“编辑模板”上更改初始模板 这似乎很清楚,除了第(5)部分,当控件失去焦点时如何更改模板 仅当包含的控件失去焦点时,才会触发失去焦点事件 下面是一篇关于它的文章 我试图实现相同的技术,但仍然没有结果,当我在控件外单击时,我无法使LostFocus事件为我工作 我的问题在哪里 我的XAML 有几个问题。让我们看看 当您在控制之外单击时,为什么没有得到LostFocus事件 我不久前也成为这个错误假

我正在开发一个简单的自定义控件,双击该控件可以进入编辑模式

这个概念是基于这个问题

双击时,它会在“编辑模板”上更改初始模板 这似乎很清楚,除了第(5)部分,当控件失去焦点时如何更改模板 仅当包含的控件失去焦点时,才会触发失去焦点事件 下面是一篇关于它的文章

我试图实现相同的技术,但仍然没有结果,当我在控件外单击时,我无法使LostFocus事件为我工作

我的问题在哪里

我的XAML


有几个问题。让我们看看

当您在控制之外单击时,为什么没有得到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>