(ViewModel)DataContext 返回 null

3

I've got the following event:

private void PlaceToken(object sender, RoutedEventArgs e)
{
    ConnectFourViewModel currentViewModel = (ConnectFourViewModel)DataContext;

    Button button = (Button)sender;

    int currentColumn = Convert.ToInt32(button.Content);

    int currentPlayer = currentViewModel.Board.CurrentPlayer;
    currentViewModel.Board.PlaceToken(currentColumn, currentPlayer);
}

在以下设置完成后:
public MainWindow()
{
    var window = new Window();
    var grid = new Grid {};
    ConnectFourViewModel ViewModel = new ConnectFourViewModel();

    //Set up rows and cols
    for(int i = 1; i<=7; i++)
    {
        var col = new ColumnDefinition();
        grid.ColumnDefinitions.Add(col);
    }
    for (int i = 1; i <= 7; i++)
    {
        var row = new RowDefinition();
        grid.RowDefinitions.Add(row);
    }

    //Set up tiles
    foreach (var item in ViewModel.Board.AllTiles)
    {
        int index = ViewModel.Board.AllTiles.IndexOf(item);

        string name =
              "Col" +
              Convert.ToString(item.Column) +
              "_Row" +
              Convert.ToString(item.Row);

        Label currentTile = new Label{ Name = name};
        Grid.SetRow(currentTile, item.Row - 1);
        Grid.SetColumn(currentTile, item.Column -1);

        //Bind
        var binding = new Binding();
        binding.Source = ViewModel.Board.AllTiles[index];
        binding.Path = new PropertyPath("Contents");

        currentTile.SetBinding(ContentProperty, binding);

        //Add
        grid.Children.Add(currentTile);
    }

    //Set up Buttons
    for (int i = 1; i <= 7; i++)
    {
        Button currentButton = new Button { };

        //binding
        var binding = new Binding();
        binding.Source = ViewModel.CurrentColumn;

        currentButton.SetBinding(ContentProperty, binding);

        //Set Column names, this has to be after the binding has been set.
        currentButton.Content = i;
        //events
        currentButton.Click += new RoutedEventHandler(PlaceToken);

        //add
        Grid.SetColumn(currentButton, i - 1);
        Grid.SetRow(currentButton, 7);
        grid.Children.Add(currentButton);
    }

    window.Content = grid;
    window.DataContext = ViewModel;
    window.Show();
    InitializeComponent();
}

我希望这一行代码:ConnectFourViewModel currentViewModel = (ConnectFourViewModel)DataContext; 可以设置currentViewModel以反映我的UI正在运行的信息。不幸的是,它返回null,我不知道为什么。
这显然凸显了我对这个主题的理解上存在的差距,但我不确定该如何解决,所以需要帮忙。有任何想法吗?我哪里出错了吗?

2
如果您在类中实例化了ViewModel,为什么要从DataContext中转换它?您可以直接使用该实例。 - Filip
1
那段代码太糟糕了,其中90%应该写在XAML中。 - H.B.
1个回答

3
您还没有在任何地方将 DataContext 分配给 ViewModel 。 假设您希望 ViewModel 是MainWindow的ViewModel,建议在Initialize Component之前将其分配如下所示。 由于它从未被分配,您正在获取null。
public MainWindow()
{
    ConnectFourViewModel ViewModel = new ConnectFourViewModel();
    . . .
    . . .
    DataContext = ViewModel ;
    InitializeComponent();
}

1
谢谢,非常简洁明了的回答。做为一个后续问题:你可以看到我已经设置了window.DataContext,认为因为我的界面实际上是在window中,所以DataContext应该适用于那个单独的窗口。为什么要为主窗口设置上下文,当所有东西都在window中呢? - MGDavies
1
我无法理解你的问题。我猜你是在询问质量反馈?你采取的方法有很多问题。你正在编写类似Winform的代码,但没有使用XAML。2. 对于你所做的事情,你不需要另一个窗口对象!你可以将所有这些控件添加到主窗口中,并将其分配给视图模型。 - Carbine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接