如何将网格内容绑定到 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;
}
}
问题是您不能直接绑定到 Grid
的 Children
集合,因为它不是 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 控件引用。
考虑使用 INotifyPropertyChanged
和 data templates 创建 Tank
和 Stability
视图模型来显示它们,而不是在视图模型中使用 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>
我有一个网格,想要将用户控件显示为网格的子项或网格的内容。单击按钮时,将根据情况显示一些用户控件。请检查 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;
}
}
问题是您不能直接绑定到 Grid
的 Children
集合,因为它不是 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 控件引用。
考虑使用 INotifyPropertyChanged
和 data templates 创建 Tank
和 Stability
视图模型来显示它们,而不是在视图模型中使用 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>