0

我有一个使用 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>
4

1 回答 1

1

注意:在这种情况下,除非我有很多额外的时间花在这上面,否则我会将其归结为对 MVVM 不完全友好的第三方控件,稍微打破“规则”,然后放一些代码在您的 View 类后面将对该文本编辑器的引用传递给您的视图模型。

但是,如果您想使用“纯无代码隐藏 MVVM”,则需要创建某种代理对象,该对象知道如何与 XamTextEditor 通信并接收来自底层视图模型的事件。这类似于 Blend/Prism 用于执行用户交互对话框的机制:“动作”对象充当视图模型(它只是引发交互请求事件)和页面上的一些其他 UI 元素之间的桥梁。

我认为解决这个问题的最“稳健”的方法是创建一个知道如何“在当前选择位置将字符串插入 XamTextEditor”的对象。

<local:XamEditorInserter 
    SourceObject="{Binding InsertTagRequest}" 
    TargetEditor="{Binding ElementName=TBody}" />

您可以通过几种方式实现此技术。最简单的方法是定义一个具有事件的接口,您的自定义“桥”对象可以订阅该事件。(TriggerBase来自 Blend SDK 公开了一个实际的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.
  }
}

在您的视图模型中,您只需定义 type 的属性ICustomTrigger,将其设置为 a ,并在需要将新标签插入文本编辑器时new CustomTrigger()调用其方法。Raise()

于 2012-04-27T17:08:18.030 回答