简体   繁体   English

数据绑定不适用于用户控件

[英]Databinding not working with usercontrol

I'm trying to implement in place editing of treenodes. 我正在尝试对treenodes进行就地编辑。 I'm fairly close but no cigar. 我很近但是没有雪茄。 All bindings seem correct. 所有绑定似乎都是正确的。 The application runs fine, no output messages, the treeview gets populated. 应用程序运行正常,没有输出消息,树视图被填充。 I'm able to select a node, press F2, I can edit the node but as soon as I hit enter the text reverts to what it was before, as if I didn't make an edit. 我可以选择一个节点,按F2键,就可以编辑该节点,但是一旦按下Enter键,文本就会恢复为之前的样子,好像我没有进行编辑一样。 If I make an edit of the Name property somewhere else in the application that change gets reflected in the EditableTextBlock, both in the TextBlock and in the TextBox. 如果我在应用程序的其他地方对Name属性进行编辑,则该更改会反映在EditableTextBlock中,无论是在TextBlock中还是在TextBox中。 Why can't I make the change persistent? 为什么我不能使更改持久化? It's as if the binding works in one way only. 好像绑定仅以一种方式起作用。

This is the user control's xaml: 这是用户控件的xaml:

<UserControl x:Class="WPFApplication.EditableTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFApplication"
x:Name="MyUserControl">
<UserControl.Resources>

    <DataTemplate x:Key="EditModeTemplate">
        <TextBox KeyDown="TextBox_KeyDown" Loaded="TextBox_Loaded" LostFocus="TextBox_LostFocus"
                 Text="{Binding Path=Text, ElementName=MyUserControl, Mode=TwoWay}"
                 Margin="0" BorderThickness="1" />
    </DataTemplate>

    <DataTemplate x:Key="DisplayModeTemplate">
        <TextBlock Text="{Binding ElementName=MyUserControl, Path=Text, Mode=TwoWay}"/>
    </DataTemplate>

    <Style TargetType="{x:Type local:EditableTextBlock}">
        <Style.Triggers>
            <Trigger Property="IsInEditMode" Value="True">
                <Setter Property="ContentTemplate" Value="{StaticResource EditModeTemplate}" />
            </Trigger>
            <Trigger Property="IsInEditMode" Value="False">
                <Setter Property="ContentTemplate" Value="{StaticResource DisplayModeTemplate}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

and the code behind: 以及后面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WPFApplication
{
    public partial class EditableTextBlock : UserControl
    {

        #region Constructor

        public EditableTextBlock()
        {
            InitializeComponent();
            base.Focusable = true;
            base.FocusVisualStyle = null;
        }

        #endregion Constructor

        #region Member Variables

        // We keep the old text when we go into editmode
        // in case the user aborts with the escape key
        private string oldText;

        #endregion Member Variables

        #region Properties

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register(
            "Text",
            typeof(string),
            typeof(EditableTextBlock),
            new PropertyMetadata(""));

        public bool IsEditable
        {
            get { return (bool)GetValue(IsEditableProperty); }
            set { SetValue(IsEditableProperty, value); }
        }
        public static readonly DependencyProperty IsEditableProperty =
            DependencyProperty.Register(
            "IsEditable",
            typeof(bool),
            typeof(EditableTextBlock),
            new PropertyMetadata(true));

        public bool IsInEditMode
        {
            get 
            {
                if (IsEditable)
                    return (bool)GetValue(IsInEditModeProperty);
                else
                    return false;
            }
            set
            {
                if (IsEditable)
                {
                    if (value) oldText = Text;
                    SetValue(IsInEditModeProperty, value);
                }
            }
        }
        public static readonly DependencyProperty IsInEditModeProperty =
            DependencyProperty.Register(
            "IsInEditMode",
            typeof(bool),
            typeof(EditableTextBlock),
            new PropertyMetadata(false));

        public string TextFormat
        {
            get { return (string)GetValue(TextFormatProperty); }
            set
            {
                if (value == "") value = "{0}";
                SetValue(TextFormatProperty, value);
            }
        }
        public static readonly DependencyProperty TextFormatProperty =
            DependencyProperty.Register(
            "TextFormat",
            typeof(string),
            typeof(EditableTextBlock),
            new PropertyMetadata("{0}"));

        public string FormattedText
        {
            get { return String.Format(TextFormat, Text); }
        }

        #endregion Properties

        #region Event Handlers

        // Invoked when we enter edit mode.
        void TextBox_Loaded(object sender, RoutedEventArgs e)
        {
            TextBox txt = sender as TextBox;

            // Give the TextBox input focus
            txt.Focus();

            txt.SelectAll();
        }

        // Invoked when we exit edit mode.
        void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            this.IsInEditMode = false;
        }

        // Invoked when the user edits the annotation.
        void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                this.IsInEditMode = false;
                e.Handled = true;
            }
            else if (e.Key == Key.Escape)
            {
                this.IsInEditMode = false;
                Text = oldText;
                e.Handled = true;
            }
        }

        #endregion Event Handlers

    }
}

The treeview then uses this datatemplate: 然后,treeview使用此数据模板:

<HierarchicalDataTemplate DataType="{x:Type localvm:TreeViewItemViewModel}" ItemsSource="{Binding Children}">
<StackPanel>
    <local:EditableTextBlock Text="{Binding Name}"/>
</StackPanel>

Ok I tried on my end and the problem was that the Text property was never set because your TextBox never lost focus (it seems). 好的,我尽力了,问题是从未设置Text属性,因为您的TextBox从未失去焦点(看来)。

So I changed the TextBox's Text binding to add UpdateSourceTrigger=PropertyChanged and a RelativeSource instead of ElementName: 因此,我更改了TextBox的Text绑定,以添加UpdateSourceTrigger = PropertyChanged和一个RelativeSource而不是ElementName:

Text="{Binding Path=Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:EditableTextBlock}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

And it worked 而且有效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM