首页 > 解决方案 > 如何将网格内容绑定到 UserControl

问题描述

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

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

我想将 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;

    }
}

标签: c#wpfbindinggriduser-controls

解决方案


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

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

确保您MainVM的设置与DataContext任何父控件一样,否则此绑定将不起作用。activeUserControl必须是使其可绑定的属性。INotifyPropertyChanged在您的中实现MainVM,以便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 控件引用。

考虑使用数据模板创建TankStability 查看模型来显示它们,而不是INotifyPropertyChanged在你的视图模型中。在这种情况下,您仍然可以使用。UserControlContentControl

<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>

推荐阅读