在 ICommand 绑定函数中编写时,属性不会更新前端

Properties don't update front-end when written within ICommand-tied function

更新 3

" 我希望这个 TextBox 中的文本应该显示在另一个 TextBox 中(在另一个视图中)"

另一个视图中的第二个文本框旨在显示与第一个文本框关联的其他信息,而不是副本。

所以用户控件包含一个文本框,比方说,总线代码。输入公交车代码后,跳出将触发从数据库中获取其他详细信息,例如公交车名称、公交车目的地、公交车型号等。 另一个视图中的其他文本框然后显示总线名称。以下所有文本框显示目的地等。当命令被调用时,我尝试写入 属性 BusName,它被分配(我调用 Notify("BusName"))但它没有显示在 UI.

希望更清楚。对于造成的任何混乱,我们深表歉意:)。

UPDATE2 - 对 blindmeis 的回应

感谢您的回复,虽然这似乎不是我要找的。 tab out 是必不可少的,因为这就是管理层希望他们的页面被填充的方式,即当您在输入代码后从 'code' 文本框中跳出时,它将使用该代码从数据库中获取数据以填充其余部分控件。这似乎没有跳出行为。至于第三个依赖项属性,它在我的原始代码中,我只是没有在这里包含它,因为第一个文本框(用户控件制表符文本框)中的值与问题无关。简单地说,我想要完成的是,当您从第一个文本框跳出时,第二个文本框必须填充。

我可以使用事件处理程序来完成此操作,但我想使用命令。我现在在想,也许命令不是去这里的方式,我应该改用事件处理程序。

如果您仍然对如何在第一个文本框之外填充第二个文本框有任何想法,请告知(通过在填充中放置一个断点,您将看到 属性 已分配。 ).如果我没有正确理解或遗漏了什么,请告诉我。谢谢!

更新! 我已经创建了一个模仿我的代码的 VS2013 解决方案,它重现了这个问题。它作为 zip 文件位于 public google 驱动器 link 中(下载图标出现需要几秒钟):

https://drive.google.com/file/d/0B89vOvsI7Ubdbk85SVlvT3U2dVU/view?usp=sharing

尽管绑定 属性 存储了新值,但您会看到第二个文本框没有更新。

非常感谢任何帮助。提前致谢。


原版post:

我有一个文本框控件,当用户在文本框中点击制表符(制表符退出)时,我将一个基于键绑定的命令绑定到该控件上以处理某些操作(以命令绑定到的方法) .

我在该页面中还有其他控件,这些控件绑定到我在该制表符连接函数中写入的视图模型中的属性。当我在构造函数或某处 'outside' 命令调用中编写我的属性时,它们似乎工作正常并且值显示在页面上,但是当我在该命令调用中编写它们时,vm 中的属性包含值但是不要出现在 UI

知道为什么以及如何解决吗?

在此先致谢

来自XAML:

        <TextBox Name="txtCode" Text="{Binding Path=CodeValue, Mode=TwoWay,      UpdateSourceTrigger=PropertyChanged}">
        <TextBox.InputBindings>
            <KeyBinding Key="Tab"  Command="{Binding RetrieveRecordCmd}" >  </KeyBinding>
        </TextBox.InputBindings>
    </TextBox>

来自虚拟机:

       RetrieveRecordCmd = new GSSCommand(RetrieveRecord, param => this.CanExecuteRetrieveRecordCmd);

命令绑定函数:

        public void RetrieveRecord(object obj)
    {
        objPie = null;

        //Check if a record exists for that code
        gssSvcMethodStatusBase = gssSvcClientBase.ReadPies(ref gssSvcGlobalVarsBase, out objPie, out grfaBase, CodeValue);

        if ((objPie != null))  // && (objPie.DateCreated > DateTime.MinValue))
            PopulatePage(objPie);
        else if (objPie == null)            
            InitiateCreateNew();            
        else            
            return;            
    }

这可行,但我不知道这是否是您想要的行为。

<UserControl x:Class="ProblemDemoWPF.TextBoxTabOutUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         Name="TabOutTextUserControl"
         >
<StackPanel Margin="0,0,0,0" Orientation="Horizontal">
    <Label Content="UserControl (ucTextBox)->"></Label>
    <TextBox Width="80" Height="30" BorderBrush="Black"
                            BorderThickness="2"                             
                        HorizontalAlignment="Center"
                         VerticalAlignment="Center"
                         Text="{Binding ElementName=TabOutTextUserControl, Path=CodeValue}">
    </TextBox>
</StackPanel>
</UserControl>

没有 DataContext 的正确绑定的新依赖属性

public partial class TextBoxTabOutUserControl : UserControl
{
    public static readonly DependencyProperty CodeValueProperty = 
        DependencyProperty.Register("CodeValue", typeof(string), typeof(TextBoxTabOutUserControl));

    public string CodeValue
    {
        get { return (string)GetValue(CodeValueProperty); }
        set { SetValue(CodeValueProperty, value); }
    }


    public TextBoxTabOutUserControl()
    {
        InitializeComponent();
    }
}

只需将两者都绑定到 LocTextBoxText

<Window x:Class="ProblemDemoWPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:loc="clr-namespace:ProblemDemoWPF"
     Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <loc:TextBoxTabOutUserControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="left" 
                                  CodeValue="{Binding Buscode, Mode=OneWayToSource}"/>

    <Label Content="Busname" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left"></Label>
    <TextBox Width="100" Grid.Row="1" Grid.Column="1" Text="{Binding Path=Busname, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>

    <Label Content="Busdestination" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left"></Label>
    <TextBox Width="100" Grid.Row="2" Grid.Column="1" Text="{Binding Path=Busdestination, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>

    <Label Content="Busmodel" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left"></Label>
    <TextBox Width="100" Grid.Row="3" Grid.Column="1" Text="{Binding Path=Busmodel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</Grid>
</Window>

将通知添加到 属性 setter

class MainWindowViewModel : INotifyPropertyChanged
{
    private String _buscode;
    private string _busname;
    private string _busdestination;
    private string _busmodel;

    public String Buscode
    {
        get
        {
            return _buscode;
        }
        set
        {
            if (_buscode != value)
            {
                _buscode = value;
                Notify("Buscode");
                FetchData(_buscode);
            }
        }
    }

    private void FetchData(string buscode)
    {
        //DB stuff
        this.Busname = "Name 1234";
        this.Busmodel = "Model 1234";
        this.Busdestination = "Destination 1234";

    }

    public string Busname
    {
        get { return _busname; }
        set { _busname = value; Notify("Busname"); }
    }

    public string Busdestination
    {
        get { return _busdestination; }
        set { _busdestination = value; Notify("Busdestination"); }
    }

    public string Busmodel
    {
        get { return _busmodel; }
        set { _busmodel = value; Notify("Busmodel"); }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void Notify(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

看起来您已经实现了严格意义上的 INotifyPropertyChanged 接口,但缺少实际功能。界面本身不会自动为您提供更改通知。您还需要在每个 属性 更改时触发 PropertyChanged 事件。标准模式如下所示:

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value)
                return;
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }

您应该养成以这种格式编写您打算绑定到 UI 的所有可变属性的习惯。片段可以使这更容易始终如一地进行。