提问人:Pavel Dubsky 提问时间:10/23/2020 更新时间:10/23/2020 访问量:829
对于完全加载后新设置的 ContentControl 内容,不会触发 Loaded 事件
Loaded event is not fired for newly set content of ContentControl after it has been fully loaded
问:
我希望能够将 的属性绑定到 ViewModel 属性,以便当 ViewModel 更改其属性的值时,将根据 确定 ,并为新呈现的 View 触发事件(即根据 选择)。下面的代码示例演示了该问题,即更改时不会触发事件。Content
ContentPresenter
Content
ContentPresenter
DataTemplate
Loaded
DataTemplate
Loaded
Content
据我了解,更改时不会触发事件,我对此感到满意。问题是新加载的上下文的事件不会被触发,但它仍然会被呈现出来。有什么方法可以实现这种行为吗?Loaded
Content
ContentPresenter
Loaded
主窗口
<Window x:Class="WpfLoadProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfLoadProblem"
Height="450"
Title="MainWindow"
Width="800">
<Window.Resources>
<DataTemplate DataType="{x:Type local:ContentViewModel}">
<local:ContentUserControl/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="5"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Command="{Binding Path=ChangeContentCommand}" Grid.Row="0">Change Content</Button>
<ContentPresenter Content="{Binding Path=Content}" Grid.Row="2"/>
</Grid>
</Window>
MainWindowView模型
internal sealed class MainWindowViewModel : INotifyPropertyChanged
{
private object content;
public MainWindowViewModel()
{
ChangeContentCommand = new DelegateCommand(ChangeContent);
}
public ICommand ChangeContentCommand { get; }
public object Content
{
get => content;
private set
{
if (content != value)
{
content = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Content)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void ChangeContent()
{
// After setting this property Loaded event is not fired for the 2nd and consecutive times.
Content = new ContentViewModel();
}
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
ContentUserControl
<UserControl x:Class="WpfLoadProblem.ContentUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors">
<i:Interaction.Triggers>
<i:EventTrigger x:Name="Loaded">
<i:InvokeCommandAction Command="{Binding Path=LoadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox ItemsSource="{Binding Path=Numbers}"/>
</UserControl>
ContentView模型
internal sealed class ContentViewModel
{
private readonly ICollection<int> numbers = new ObservableCollection<int>();
public ContentViewModel()
{
LoadedCommand = new DelegateCommand(Load);
}
public ICommand LoadedCommand { get; }
public IEnumerable<int> Numbers => numbers;
private void Load()
{
int start = numbers.Count == 0 ? 0 : numbers.Max();
numbers.Clear();
for (int number = start; number < start + 5; ++number)
{
numbers.Add(number);
}
}
}
答:
这只是一个猜测,但由于类型永远不会改变,因此使用的类型也可能永远不会改变。相反,它只是继续使用相同的 .但是,将要改变的是 .尝试使用 DataContextChanged
事件,看看它是否有效。Content
DataTemplate
DataTemplate
DataContext
Loaded
评论
DataContextChanged
ContentPresenter
Loaded
UserControl
DataContextChanged
ContentPresenter
Loaded
DataContextChanged
除非卸载控件,否则不会触发该事件。而且不是在变化的时候。将缓存应用的内容,并且仅更新数据上下文和绑定。Loaded
Content
DateTemplate
在设置属性后,应直接在调用方法中调用 或调用,而不是依赖于引发的事件:Loaded
LoadedCommand
Load()
ChangeContent()
Content
private void ChangeContent()
{
var viewModel = = new ContentViewModel();
Content = viewModel;
viewModel.LoadedCommand.Execute(null);
}
评论
上一个:在变量中存储返回前的值
评论