wpf IViewFor Bind 扩展方法如何工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28234151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:53:48  来源:igfitidea点击:

How works IViewFor Bind extension method?

wpfmvvmdata-bindingreactiveui

提问by Евгений Савин

Simple question, but I dons see solution. Or may be dont understand how Bind method works. The goal is two way binding between ViewModel and DataContext properties.

简单的问题,但我没有看到解决方案。或者可能不明白 Bind 方法是如何工作的。目标是 ViewModel 和 DataContext 属性之间的两种方式绑定。

    public MainWindow()
    {
        InitializeComponent();

        this.Bind(this, v => v.DataContext, v => v.ViewModel);
    }

    public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
        "ViewModel", typeof (string), typeof (MainWindow));

    public string ViewModel
    {
        get { return (string) GetValue(ViewModelProperty); }
        set { SetValue(ViewModelProperty, value); }
    }

when I set ViewModel property, I get InvalidCastException "System.String" to "WpfApplication1.MainWindow".

当我设置 ViewModel 属性时,我得到 InvalidCastException "System.String" 到 "WpfApplication1.MainWindow"。

But xaml binding works perfectly.

但是 xaml 绑定工作得很好。

<MainWindow 
   DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel, Mode=TwoWay}" ...

full xaml.cs/xaml code is here http://pastebin.com/iCKeNS7R

完整的 xaml.cs/xaml 代码在这里http://pastebin.com/iCKeNS7R

Where I wrong ?

我错在哪里?

update:this code:

更新:此代码:

this.WhenAnyValue(v => v.ViewModel).BindTo(this, v => v.DataContext); this.WhenAnyValue(v => v.DataContext).BindTo(this, v => v.ViewModel);

this.WhenAnyValue(v => v.ViewModel).BindTo(this, v => v.DataContext); this.WhenAnyValue(v => v.DataContext).BindTo(this, v => v.ViewModel);

also works as expected

也按预期工作

update 2Question: Does this.Bind(viewModelParam, ...) ignore viewModelParam argument ??

更新 2问题:this.Bind(viewModelParam, ...) 是否忽略 viewModelParam 参数??

example^ http://pastebin.com/e2aPaGNc

示例^ http://pastebin.com/e2aPaGNc

I bind to _otherViewModel, but when type text into textBox, ViewModel.StrProp changed, not _otherViewModel.

我绑定到 _otherViewModel,但是当在 textBox 中输入文本时,ViewModel.StrProp 发生了变化,而不是 _otherViewModel。

Does anybody know, how this.Bind work ??

有人知道 this.Bind 是如何工作的吗?

回答by Ana Betts

Binddoesn't work between ViewModel and DataContext because the types don't match (i.e. I could set DataContext to '4' and now it can't assign that to ViewModel).

Bind在 ViewModel 和 DataContext 之间不起作用,因为类型不匹配(即我可以将 DataContext 设置为“4”,现在它无法将其分配给 ViewModel)。

However, if you are using ReactiveUI bindings, you don't needDataContext at all, you should just use RxUI bindings everywhere. Please ignore the other answers on this thread that tell you how to do things the wrong way.

但是,如果您使用 ReactiveUI 绑定,则根本不需要DataContext,您应该在任何地方使用 RxUI 绑定。请忽略此线程上的其他答案,这些答案告诉您如何以错误的方式做事。

回答by Sagiv b.g

you can just bind the ViewModel via XAML:

您可以通过 XAML 绑定 ViewModel:

<Window x:Class="YourNameSpace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:YourNameSpace"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ViewModel:MainViewModel x:Key="MainViewModel"/>
    </Window.Resources>
    <Grid>
        <TextBox Text="{Binding YourProperty, Mode=TwoWay, Source={StaticResource MainViewModel}, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Window>

your viewmodel should implement INotifyPropertyChanged.

您的视图模型应该实现 INotifyPropertyChanged。

public class MainViewModel : INotifyPropertyChanged
{
    private string _yourProperty;
    public string YourProperty
    {
        get { return _yourProperty; }
        set { _yourProperty = value; OnPropertyChanged("YourProperty"); }
    }


    public MainViewModel()
    {
        _yourProperty = "Some string";
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion
}