【问题标题】:How to bind grid content to a UserControl如何将网格内容绑定到 UserControl
【发布时间】:2020-07-06 06:16:47
【问题描述】:

我有一个 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;

    }
}

【问题讨论】:

  • 拥有一个 UserControl 是一个视图模型不是 MVVM。您可能想使用这样的 ItemsControl:stackoverflow.com/q/6995844/1136211
  • 您想在ContentPanel 中显示UserControl 吗?或者你想做什么? MainVM的目的是什么?

标签: c# wpf binding grid user-controls


【解决方案1】:

问题是您不能直接绑定到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 视图模型来显示它们,而不是在视图模型中使用UserControls。在这种情况下,您仍然可以使用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>

【讨论】:

  • 非常感谢您的回答,我测试了第一个解决方案,但当我更改 ActiveUserControl 时,它对 GUI 没有影响。
  • 我更正了代码中的拼写错误,它是ActiveUserControl,一定要更新它。为ActiveUserControl 分配一个不同的实例就足够了。你确定你的类实现了INotifyPropertyChanged (public class MainVM : INotifyPropertyChanged)?
  • 哦,是的,我忘记实现 INotifyPropertyChanged。当我添加这部分时,它起作用了。太感谢了。我将尝试您的第二个 MVVM 解决方案。
猜你喜欢
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 2014-03-15
  • 2017-12-04
  • 2012-01-30
  • 2010-10-24
相关资源
最近更新 更多