2

我创建了一些具有可绑定“ClearCommand”ICommand 依赖属性的自定义控件(不是用户控件)。这个属性将完全按照它的意思做:它将清除控件中的所有值(文本框等)。我还将(一些)相同的属性绑定到我在下面描述的 VM。

现在我被困在尝试在以下 MVVM 场景中触发这些控件中的 ClearCommand :

我在我的视图中添加了一些这样的控件。该视图还包括一个绑定到我的 ViewModelSaveCommand DelegateCommand属性的“保存”按钮。

我需要做的是,在成功保存后,VM 应该触发ClearCommand在视图中找到的那些控件。在此处输入图像描述

更新

我在下面添加了代码示例。我有一些类似于 ExampleCustomControl 的控件。另外,请注意,如果完全关闭,我愿意重组其中的一些。

示例控制片段:

public class ExampleCustomControl : Control {

    public string SearchTextBox { get; set; }
    public IEnumerable<CustomObject> ResultList { get; set; }

    public ExampleCustomControl() {
        ClearCommand = new DelegateCommand(Clear);
    }

    /// <summary>
    /// Dependency Property for Datagrid ItemSource.
    /// </summary>
    public static DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem",
        typeof(CustomObject), typeof(ExampleCustomControl), new PropertyMetadata(default(CustomObject)));

    public CustomObject SelectedItem {
        get { return (CustomObject)GetValue(SelectedCustomObjectProperty); }
        set { SetValue(SelectedCustomObjectProperty, value); }
    }

    public static DependencyProperty ClearCommandProperty = DependencyProperty.Register("ClearCommand", typeof(ICommand),
            typeof(ExampleCustomControl), new PropertyMetadata(default(ICommand)));

    /// <summary>
    /// Dependency Property for resetting the control
    /// </summary>
    [Description("The command that clears the control"), Category("Common Properties")]
    public ICommand ClearCommand {
        get { return (ICommand)GetValue(ClearCommandProperty); }
        set { SetValue(ClearCommandProperty, value); }
    }

    public void Clear(object o) {
        SearchTextBox = string.Empty;
        SelectedItem = null;
        ResultList = null;
    }
}

示例视图片段:

<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="30"/>
    </Grid.RowDefinitions>
    <control:ExampleCustomControl Grid.Row="0"
        SelectedItem="{Binding Selection, UpdateSourceTrigger=PropertyChanged}" />
    <Button Grid.Row="1" x:Name="ResetButton" Command="{Binding SaveCommand}">
        Save
    </Button>
</Grid>

示例视图模型:

public class TestViewModel : WorkspaceTask {
    public TestViewModel() {
        View = new TestView { Model = this };
        SaveCommand = new DelegateCommand(Save);
    }

    private CustomObject _selection;
    public CustomObject Selection {
        get { return _selection; }
        set {
            _selection = value;
            OnPropertyChanged("Selection");
        }
    }

    public DelegateCommand SaveCommand { get; private set; }
    private void Save(object o) {
        // perform save
        // clear controls
    }
}
4

3 回答 3

2

正如其他人所说,VM 不应该直接在 MVVM 中知道视图,因此 VM 在您的自定义控件上触发某些内容以清除所有内容并没有任何意义。

我会将DataContext自定义控件设置为一个对象,该对象具有您要清除的所有属性,这些属性都绑定(双向)到您的文本框等。然后在 Save() 方法中,您可以设置一个新对象(自定义控件DataContext绑定到)并且所有属性都将为您清除(假设您已INotifyPropertyChanged在对象上实现)。

更新:

根据我的评论,请参阅当前设置的解决方法示例(未经测试的顺便说一句):

    public static DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem",
        typeof(CustomObject), typeof(ExampleCustomControl), new PropertyMetadata(default(CustomObject), OnSelectedItemChanged));


    private static void OnSelectedItemChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        var cont = source as ExampleCustomControl;

            //do all the clearing of txtboxes etc here....
        cont.SearchTextBox = string.Empty;
    }

但我仍然会尝试将所有这些移到 VM 中。即有一个清除命令,就像您使用保存命令并将文本框文本等绑定到VM中的属性一样,当调用该命令时,它会清除所有内容,然后您也可以轻松地从VM中的Save方法调用。但显然我不知道您从长远来看要达到什么目标,也不知道 selectedItem 和文本框等是如何相关的,所以我猜(一如既往)取决于。

于 2012-05-02T13:01:51.860 回答
1

听起来你正在以错误的方式思考这个问题。在 MVVM 中,ViewModel 永远不应该知道有关自定义控件的任何信息(因此您在使用此 Clear 功能时遇到问题)。

您的要求有点模糊,但您是否考虑过:

1)如果属性是从虚拟机绑定的,控件是否不能检测到这些属性何时更改?

2) 如果您确实需要从 XAML 层调用 Clear 并希望将其保持为纯 MVVM,请考虑类似于 Expression Blend SDK 的CallMethodAction

于 2012-05-02T12:39:59.940 回答
0

作为我评论的后续行动。我怀疑您的命令是针对 View 并TextBox直接清除 es 。相反,让您的命令以 ViewModel 为目标并清除 View 绑定到的属性。然后,您可以将该命令作为 ViewModel 上的一个属性,并在需要时调用它。

于 2012-05-02T12:42:11.113 回答