我有一个使用MVVM构建的WPF应用程序。该控件有一个文本框,我需要在其中插入标签。我使用的控件是 XamT 。
因此,当用户按下插入按钮时,我需要查询聚焦控件的SelectionStart值,这样我就可以在属性文本索引处插入标记。
选择开始属性不是DP,因此我无法对其值进行数据绑定并接收更改通知。
我想知道MVVM中有人会这样做吗?
控件定义为:
<x:XamTextEditor Grid.Column="1" Grid.Row="3"
Grid.ColumnSpan="2" Margin="0 5 0 5"
Template="{StaticResource ResourceKey=MyTextEditorTemplate}"
Name="TBody"
Text="{Binding Body}"
TextWrapping="Wrap"
IsAlwaysInEditMode="{Binding InEditMode,Mode=OneWay}"
AcceptsReturn="True" AcceptsTab="True">
<igEditors:ValueConstraint Nullable="False" MinLength="1"/>
</x:XamTextEditor>
答案 0 :(得分:1)
注意:在这种情况下,除非我有更多的额外时间花在这上面,否则我会把它归结为一个不完全MVVM友好的第三方控件,打破“规则”一点,然后只是在View类中添加一些代码,将对该文本编辑器的引用传递给您的视图模型。
但是如果你想要“纯粹的无代码隐藏的MVVM”,你需要创建某种代理对象,它知道如何与XamTextEditor进行通信,并从底层视图模型接收事件。这类似于Blend / Prism用于执行用户交互对话框的机制:“action”对象充当视图模型(简单地引发交互请求事件)与页面上的一些其他UI元素之间的桥梁。 p>
我认为最有效的方法是创建一个知道如何“在当前选择位置将字符串插入XamTextEditor”的对象。
<local:XamEditorInserter
SourceObject="{Binding InsertTagRequest}"
TargetEditor="{Binding ElementName=TBody}" />
您可以通过几种方式实现此技术。最简单的方法是定义一个具有事件的接口,您的自定义“桥”对象可以订阅该事件。 (Blend SDK中的TriggerBase
公开了一个实际的List<Action>
,这实际上是相同的,但实现的代码要多一些):
public class CustomTriggerEventArgs : EventArgs
{
public string StringData
{
get;
set;
}
}
public interface ICustomTrigger
{
event EventHandler<CustomTriggerEventArgs> CustomTriggerRaised;
}
public class CustomTrigger : ICustomTrigger
{
event EventHandler<CustomTriggerEventArgs> CustomTriggerRaised;
public void Raise(string s)
{
if (this.CustomTriggerRaised != null)
{
this.CustomTriggerRaised(this, new CustomTriggerEventArgs { StringData = s });
}
}
}
当SourceObject
被更改时,您的桥对象需要连接到该事件:
public DependencyObject SourceObject
{
get
{
return this.GetValue(SourceObjectProperty) as DependencyObject;
}
set
{
if (value is ICustomTrigger)
{
((ICustomTrigger)value).CustomTriggerRaised += this.TriggerRaised;
}
this.SetValue(SourceObjectProperty, value);
}
}
public void TriggerRaised(object sender, CustomTriggerEventArgs e)
{
if (this.TargetEditor != null)
{
var sel = this.TargetObject.SelectionStart;
var tag = e.StringData;
// do whatever.
}
}
在您的viewmodel中,您只需定义ICustomTrigger
类型的属性,将其设置为new CustomTrigger()
,并在需要在文本中插入新标记时调用其Raise()
方法编辑器。