更新TextBlock绑定不工作
本文关键字:工作 绑定 TextBlock 更新 | 更新日期: 2023-09-27 18:13:16
我有一个关于数据绑定的问题!我正在为一个"节点编辑器"编写代码,其中有一些(不同)节点。我使用BaseViewModel类,派生自INotifyPropertyChanged。
有一个'基' NodeViewModel(派生自它)与ObservableCollection和其他属性,如节点的Name属性。它的实现是这样的:
(在公共类NodeViewModel: BaseViewModel):
protected String mName = String.Empty;
public String Name {
get { return mName; }
set {
if (mName == value) {
return;
}
mName = value;
OnPropertyChanged("Name");
}
}
有一个OnPropertyChanged处理程序,看起来像这样:
( BaseViewModel )
protected virtual void OnPropertyChanged(string propertyName) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
现在我有一个额外的RoomViewModel派生自NodeViewModel。
我使用另一个不同的ViewModel,我称之为RoomCollectionViewModel来分组一些房间。现在,当我将一个房间添加到我的roomcollection中时(通过绘制它们之间的连接),我测试所有连接的房间是否具有相同的名称。
如果集合中已经存在一个具有相同房名的已连接房间(例如:我想把那两个房间的名字改成。"新1号房间"answers"新2号房间"。到目前为止没有问题。
每个节点控件(使用DataTemplates创建,set DataContext设置为ViewModel)包含一个TextBlock(一个修改过的),显示节点的名称。
这就是问题所在:
我使用修改后的Textblock,因为我希望能够通过双击来修改节点的名称。这是完美的,只有当我在代码中修改RoomViewModel的名字,这个(修改)TextBlock不会更新。
奇怪的是:当集合中两个同样命名的房间被我的代码重命名时,然后双击可编辑的TextBlock(在此过程中转换为TextBox),我已经看到修改后的Text。所以我假设我的DataBinding和我的代码是正确的,只是不完整:)
那么如何有可能强制更新我的EditableTextBlock,文本(DependencyProperty)似乎更新正确…
我希望你能理解我的问题是什么!谢谢你的帮助。更新1 这是我的EditableTextBlock的XAML代码(它来自这里:http://www.codeproject.com/Articles/31592/Editable-TextBlock-in-WPF-for-In-place-Editing)
<UserControl x:Class="NetworkUI.EditableTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:NetworkUI"
mc:Ignorable="d"
d:DesignHeight="60" d:DesignWidth="240" x:Name="mainControl">
<UserControl.Resources>
<DataTemplate x:Key="EditModeTemplate">
<TextBox KeyDown="TextBox_KeyDown" Loaded="TextBox_Loaded" LostFocus="TextBox_LostFocus"
Text="{Binding ElementName=mainControl, Path=Text, UpdateSourceTrigger=PropertyChanged}"
Margin="0" BorderThickness="1" />
</DataTemplate>
<DataTemplate x:Key="DisplayModeTemplate">
<TextBlock Text="{Binding ElementName=mainControl, Path=FormattedText}" Margin="5,3,5,3" MouseDown="TextBlock_MouseDown" />
</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>
下面是代码隐藏文件:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace NetworkUI {
/// <summary>
/// Interaction logic for EditableTextBlock.xaml
/// </summary>
public partial class EditableTextBlock : UserControl {
#region Dependency Properties, Events
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(EditableTextBlock),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static readonly DependencyProperty IsEditableProperty =
DependencyProperty.Register("IsEditable", typeof(Boolean), typeof(EditableTextBlock), new PropertyMetadata(true));
public static readonly DependencyProperty IsInEditModeProperty =
DependencyProperty.Register("IsInEditMode", typeof(Boolean), typeof(EditableTextBlock), new PropertyMetadata(false));
public static readonly DependencyProperty TextFormatProperty =
DependencyProperty.Register("TextFormat", typeof(String), typeof(EditableTextBlock), new PropertyMetadata("{0}"));
#endregion ///Dependency Properties, Events
#region Variables and Properties
/// <summary>
/// We keep the old text when we go into editmode
/// in case the user aborts with the escape key
/// </summary>
private String oldText;
/// <summary>
/// Text content of this EditableTextBlock
/// </summary>
public String Text {
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// Is this EditableTextBlock editable or not
/// </summary>
public Boolean IsEditable {
get { return (Boolean)GetValue(IsEditableProperty); }
set { SetValue(IsEditableProperty, value); }
}
/// <summary>
/// Is this EditableTextBlock currently in edit mode
/// </summary>
public Boolean IsInEditMode {
get {
if (IsEditable)
return (Boolean)GetValue(IsInEditModeProperty);
else
return false;
}
set {
if (IsEditable) {
if (value)
oldText = Text;
SetValue(IsInEditModeProperty, value);
}
}
}
/// <summary>
/// The text format for the TextBlock
/// </summary>
public String TextFormat {
get { return (String)GetValue(TextFormatProperty); }
set {
if (value == "")
value = "{0}";
SetValue(TextFormatProperty, value);
}
}
/// <summary>
/// The formatted text of this EditablTextBlock
/// </summary>
public String FormattedText {
get { return String.Format(TextFormat, Text); }
}
#endregion ///Variables and Properties
#region Constructor
/// <summary>
/// Default constructor for the editable text block
/// </summary>
public EditableTextBlock() {
InitializeComponent();
Focusable = true;
FocusVisualStyle = null;
}
#endregion ///Constructor
#region Methods, Functions and Eventhandler
/// <summary>
/// Invoked when we enter edit mode
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
void TextBox_Loaded(object sender, RoutedEventArgs e) {
TextBox txt = sender as TextBox;
/// Give the TextBox input focus
txt.Focus();
txt.SelectAll();
}
/// <summary>
/// Invoked when we exit edit mode
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
void TextBox_LostFocus(object sender, RoutedEventArgs e) {
IsInEditMode = false;
}
/// <summary>
/// Invoked when the user edits the annotation.
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
void TextBox_KeyDown(object sender, KeyEventArgs e) {
if (e.Key == Key.Enter) {
IsInEditMode = false;
e.Handled = true;
}
else if (e.Key == Key.Escape) {
IsInEditMode = false;
Text = oldText;
e.Handled = true;
}
}
/// <summary>
/// Invoked when the user double-clicks on the textblock
/// to edit the text
/// </summary>
/// <param name="sender">Sender (the Textblock)</param>
/// <param name="e">Event arguments</param>
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) {
if (e.ClickCount == 2)
IsInEditMode = true;
}
#endregion ///Methods, Functions and Eventhandler
}
谢谢你的帮助!
更新2
我修改了下面一行代码:
<TextBlock Text="{Binding ElementName=mainControl, Path=FormattedText}" Margin="5,3,5,3" MouseDown="TextBlock_MouseDown" />
:
<TextBlock Text="{Binding ElementName=mainControl, Path=Text}" Margin="5,3,5,3" MouseDown="TextBlock_MouseDown" />
,现在它正在工作!
我没有看到TextBlock使用FormattedText放在首位!啊,非常感谢你,现在一切更新完美!
作为帖子Lee O.问题确实是从我的EditableTextBlock控件的绑定属性。
TextBlock使用了由我的Binding更新的FormattedText属性。现在我对TextBlock和TextBox控件都使用Text属性。
我只是从我的EditableTextBlock中删除了FormattedText属性以及TextFormatProperty (DependencyProperty)和TextFormat属性,因为我不打算使用这些。
再次感谢您!