自定义 WPF 就地编辑文本控件的方法
我正在开发一项功能,该功能允许用户单击空白区域(例如画布)并在单击的位置添加一段文本。单击后,他们可以立即编辑文本、更改前景、字体大小等。有点像向 PowerPoint 幻灯片添加一段文本。
我想知道这种控制的最佳方法是什么。我最初的想法是一个自定义控件(继承自 Control),它有两个内部 TemplatePart:一个 TextBlock 和一个 TextBox。我将有两种视觉状态:查看和编辑。我将在名为 Text 的自定义控件上有一个字符串依赖属性,两个模板部分将其绑定到它们自己的 Text 属性上。当用户单击该控件时,它将进入编辑模式,TextBlock 折叠并且 TextBox 可见。当 TextBox 失去焦点时,控件将进入查看模式并且 TextBlock 变得可见。当用户在编辑模式下编辑文本时,Text 属性会更新,并且所有绑定都会反映新的 Text 值。
我对这种方法的担忧是我必须包装的可绑定属性的数量。例如,Control 具有 Foreground、FontSize 和 FontFamily 属性。我希望将这些属性带入我的两个模板部件控件中,因为它们应该反映用户始终希望看到的内容 - 无论是在查看模式还是编辑模式下。例如,在自定义控件上设置 Foreground=Red 意味着内部 TextBox 和 TextBlock 也应具有红色前景。因此,我必须在 OnApplyTemplate 中为两个模板部分的每个属性连接绑定:
public override void OnApplyTemplate(){
// ... stuff ...
var foregroundBinding = new Binding
{
Source = this,
Path = new PropertyPath("Foreground")
};
myTextBox.SetBinding(TextBox.ForegroundProperty, foregroundBinding);
myTextBlock.SetBinding(TextBlock.ForegroundProperty, foregroundBinding);
// repeat for every other property, such as font size,
// font family, width, maxwidth, height, maxheight,
// horizontal alignment, yadda yadda yadda...
}
鉴于我可能想要从自定义控件传输到这些内部模板部分的数十个属性,这似乎是一种乏味的方法将很难维护 - 特别是如果我稍后更改模板部分的策略。
有更好的方法吗,还是我走在正确的道路上?
I'm working on a feature that will allow a user to click onto a blank area (e.g. a Canvas) and add a span of text where they click. After they click, they can immediately edit the text, change the foreground, font size, etc. Kind of like adding a span of text to a PowerPoint slide.
I'm wondering what the best approach for such a control would be. My initial thought would be a custom control (inherit from Control) that has two internal TemplateParts: a TextBlock and a TextBox. I will have two visual states: Viewing and Editing. I'll have a string dependency property on the custom control called Text that the two template parts are bound to on their own Text properties. When the user clicks on the control, it goes into Editing mode, the TextBlock is collapsed and the TextBox is visible. When the TextBox loses focus, the control goes into Viewing mode and the TextBlock becomes visible. When the user edits the text in Editing mode, the Text property is updated and all the bindings reflect the new Text value.
My concern with this approach is the number of bindable properties I'm going to have to wrap. For example, Control has Foreground, FontSize, and FontFamily properties. I want these properties to be carried into my two template part controls because they should reflect what the user wants to see at all times - both in Viewing and Editing mode. For example, setting Foreground=Red on the custom control means the internal TextBox and TextBlock should also have a Red foreground. Thus, I have to wire up the bindings in OnApplyTemplate for every property for both template parts:
public override void OnApplyTemplate(){
// ... stuff ...
var foregroundBinding = new Binding
{
Source = this,
Path = new PropertyPath("Foreground")
};
myTextBox.SetBinding(TextBox.ForegroundProperty, foregroundBinding);
myTextBlock.SetBinding(TextBlock.ForegroundProperty, foregroundBinding);
// repeat for every other property, such as font size,
// font family, width, maxwidth, height, maxheight,
// horizontal alignment, yadda yadda yadda...
}
Given that there are possibly dozens of properties I'd want to transfer from my custom control to these internal template parts, this seems like a tedious approach that will be difficult to maintain - especially if I change my strategy for the template parts later on.
Is there a better approach, or am I on the right track here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么你需要 TextBlock 和 TextBox?根据你的说法,仅 TextBox 就足够了。您将应用具有一些触发器的样式,这些触发器会根据 IsKeyboardFocused。
why do you need both, a TextBlock and a TextBox? From what you say, the TextBox alone would be enough. You would apply a style that has some triggers that change the looks depending on IsKeyboardFocused.
在 XAML 中创建 UserControl 并定义 TextBox 和 TextBlock 并将其绑定到自定义 DependencyObject 或放入 UserControl 代码后面的依赖项属性可能会更容易。两个控件可以绑定到相同的属性。在查看模式下将文本框可见性设置为折叠,在编辑模式下将其设置为可见。最初进入编辑模式时,请确保将鼠标光标聚焦在文本框中。如果需要,我可以提供更多详细信息,但目前我是通过智能手机输入的。
It might be easier to create a UserControl in XAML with the TextBox and TextBlock defined and bound to either a custom DependencyObject or to dependency properties that you put in the UserControl code behind. Both controls could bind to the same properties. Set the TextBox visibility to collapsed when in view mode and set it to visible when in edit mode. Be sure to focus the mouse cursor in the TextBox when initially put in edit mode. I can give more details if wanted, but at the moment I'm typing this from a smart phone.
我通过在文本块上按需打开一个弹出窗口以不同的方式解决了这个问题。文本编辑弹出窗口显示一个文本框,该文本框复制所有文本块的外观和感觉而无需绑定。当弹出窗口关闭并且文本块文本被更新时,更改将被丢弃。
I solved this problem differently by opening up a popup on demand exactly over the textblock. The text edit popup displays a textbox that copies all the textblock look and feel without binding. On the popup closes and the textblock text is updated, on the changes are discarded.