如何将网格内容绑定到 UserControl

How to bind grid content to a UserControl

我有一个网格,想要将用户控件显示为网格的子项或网格的内容。单击按钮时,将根据情况显示一些用户控件。请检查 xaml 部分和后面的代码。

 <Grid x:Name="ContentPanel" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
  Margin="5,5,5,5">
 </Grid>

我想将网格内容绑定到下面的 activeUserControl 对象。

 public class MainVM
  {
    public UserControl activeUserControl;
    Stability stability;
    Tank tank;

    public MainVM()
    {

        stability = new Stability();
        tank = new Tank();
        activeUserControl = stability;

        stability.Visibility = Visibility.Visible;

    }
}

问题是您不能直接绑定到 GridChildren 集合,因为它不是 DependencyProperty。为此,您必须实现附加属性或行为。但是,您可以将 ContentControl 放入 Grid 或替换它作为解决方法。然后将其 Content 绑定到视图模型中的 activeUserControl 属性。通常属性以大写字母开头,所以我对其进行了调整。

<Grid x:Name="ContentPanel" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,5,5,5">
  <ContentControl Content="{Binding ActiveUserControl}"/>
</Grid>

确保您的 MainVM 在任何父控件中设置为 DataContext,否则此绑定将不起作用。 activeUserControl 必须是 属性 才能使其可绑定。在您的 MainVM 中实施 INotifyPropertyChanged,以便 ContentControl 在 属性 更改并调整其 Content 时收到通知。

// Implement "INotifyPropertyChanged" so controls get notified about property changes
public class MainVM : INotifyPropertyChanged
{
    // Backing field of the "ActiveUserControl" property
    private UserControl _activeUserControl;
    
    public UserControl ActiveUserControl
    {
        get => _activeUserControl;
        set
        {
            // Only set the value if it has changed
            if (_activeUserControl != value)
            {
                _activeUserControl = value;

                // Signal to the control that it needs to update the value
                OnPropertyChanged(nameof(ActiveUserControl));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public MainVM()
    {
        // ...your code.

        ActiveUserControl = stability;

        // ...your code.
    }

    protected virtual void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

这应该可以解决您的问题,但您的代码仍然是 MVVM 和代码隐藏的混合体。理想情况下,您不应在视图模型中有任何 UI 控件引用。

考虑使用 INotifyPropertyChangeddata templates 创建 TankStability 视图模型来显示它们,而不是在视图模型中使用 UserControl。在这种情况下,您仍然可以使用 ContentControl

<ContentControl Content="{Binding activeUserControl}">
    <ContentControl.Resources>
        <DataTemplate DataType={x:Type TankViewModel}>
            <!-- ...data template equivalent of your "Tank" user control. -->
        </DataTemplate>
        <DataTemplate DataType={x:Type StabilityViewModel}>
            <!-- ...data template equivalent of your "Stability" user control. -->
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>