如何使用来自具有MVVM的子项的值从父窗口DataBind一个文本框?

时间:2017-10-18 20:59:31

标签: wpf mvvm-light

我刚从另一位不再在这里的程序员手中接过了一个项目。它是使用MVVM Pattern创建的(使用MVVM Light工具包)。我是MVVM的新手,并且一直在尝试快速学习基础知识。目前,我无法将子窗口中的选定值返回到父窗口。

从另一篇关于SO的帖子中我了解到我应该为父母和孩子使用相同的ViewModel,所以我认为我有正确的基础知识。但是,我无法将所选值恢复为父级。下面是一组类似于生产代码的示例代码。

我的两个页面的ViewModel都在这里

public class MainViewModel : ViewModelBase
{
    private Vendor selectedVendor = null;
    List<Vendor> vendors;

    public MainViewModel()
    {
        OpenVendorWindowCommand = new RelayCommand(VendorSelect);
        VendorSelectedCommand = new RelayCommand(VendorSelected);
        LoadVendors();
    }

    public ICommand OpenVendorWindowCommand { get; private set; }
    public ICommand VendorSelectedCommand { get; private set; }

    void VendorSelect()
    {
        Messenger.Default.Send(new NotificationMessage("SelectVendor"));
    }

    public Vendor SelectedVendor
    {
        get { return selectedVendor; }
        set
        {
            if (selectedVendor != value)
            {
                selectedVendor = value;
                RaisePropertyChanged();
            }
        }
    }

    void VendorSelected()
    {
        Console.WriteLine(SelectedVendor.VendorName);
    }

    public List<Vendor> Vendors
    {
        get
        {
            return vendors;
        }
        set
        {
            if (vendors != value)
            {
                vendors = value;
                RaisePropertyChanged();
            }
        }
    }

    private void LoadVendors()
    {
        DataTable dt = new DataTable();
        dt = Vendor.GetVendors();
        Vendors = new List<Vendor>();

        foreach (DataRow row in dt.Rows)
        {
            Vendors.Add(new Vendor()
            {
                VendorID = Convert.ToInt32(row["VendorID"]),
                VendorCode = Convert.ToString(row["VendorCode"]),
                VendorName = Convert.ToString(row["VendorName"])
            });
        }
    }
} 

我正在打开子窗口,我可以从ListBox中选择供应商。选择之后,我按下一个按钮(VendorSelectedCommand),此时我希望父窗口上的文本框用SelectedVendor.VendorName值填充。

这是我儿童窗口的XAML

    <StackPanel VerticalAlignment="Center">
        <ListBox
            Height="200"
            Margin="5"
            HorizontalAlignment="Stretch"
            Background="GhostWhite"
            ItemsSource="{Binding Vendors}"
            SelectedItem="{Binding Path=SelectedVendor, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="3">
                        <StackPanel Margin="15">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="175" />
                                    <ColumnDefinition Width="100" />
                                </Grid.ColumnDefinitions>
                                <TextBlock
                                    Grid.Column="0"
                                    FontWeight="SemiBold"
                                    Foreground="Black"
                                    Text="{Binding VendorName}" />
                                <TextBlock
                                    Grid.Column="1"
                                    FontWeight="SemiBold"
                                    Foreground="Black">
                                    <Run Text=" (" />
                                    <Run Text="{Binding VendorCode}" />
                                    <Run Text=") " />
                                </TextBlock>
                            </Grid>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <Button Command="{Binding VendorSelectedCommand}" Content="Send Vendor Back" />
    </StackPanel>

最后,这是父窗口的XAML,我认为是正确的绑定

    <StackPanel VerticalAlignment="Center">
        <TextBox Margin="10" Text="{Binding SelectedVendor.VendorName}" />
        <Button
            Margin="10"
            Command="{Binding OpenVendorWindowCommand}"
            Content="Select Vendor" />
    </StackPanel>

我已经尝试了我能想到的每种可能的绑定语法组合,并且在后面的代码中尝试了多种不同的方法来捕获并绑定它但是却无法正确完成它。我的ViewModel缺少什么来使其工作?

编辑为了清晰起见(以及对评论的回应)我正在添加DataContext,我在视图的构造函数中有这个。

public partial class VendorView : Window
{
    private MainViewModel _vm = null;
    public VendorView()
    {
        InitializeComponent();

        _vm = new MainViewModel();
        DataContext = _vm;
    }
}

编辑#2 我打开第二页。这是一个非常简单的示例应用程序,只有两个页面,所以我不想陷入导航困境,直到我有更好的处理绑定。

    private void NotificationMessageReceived(NotificationMessage msg)
    {
        if (msg.Notification == "SelectVendor")
        {
            var vendorView = new VendorView();
            vendorView.ShowDialog();
        }
    }

0 个答案:

没有答案