c# – 了解WPF数据绑定和值转换器交互
我试图了解下面简化的repro代码背后的实际情况.
我有一个单独的Window,其中ListBox和TextBlock绑定在一起(即master – > detail).然后我有一个带有几个属性的ViewModel – 一个字符串和一个日期.在这个日期,我实现了一个值转换器(LongDateConverter). 我在代码中有几个Debug.WriteLine()调用,导致以下输出: >启动应用 >在转换器中:ConverterProblem.MainWindowViewModel >单击列表框中的两个项目之一 >在转换器中:ConverterProblem.DataModel 第二次和第三次调用IValueConverter方法我想我明白了.第二个为null,因为ListBox还没有选定的项目.第三个是我选择的项目. 我不明白的是: >为什么第一个调用传递了MainWindowViewModel类型的值? 这是我的代码: MainWindow.xaml: <Window x:Class="ConverterProblem.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:app="clr-namespace:ConverterProblem" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <app:LongDateConverter x:Key="longDateConverter"/> </Window.Resources> <StackPanel Orientation="Horizontal"> <ListBox SelectedItem="{Binding Data}" ItemsSource="{Binding DataList}" DisplayMemberPath="Name"/> <TextBlock Text="{Binding Converter={StaticResource longDateConverter}}" DataContext="{Binding Data}" /> </StackPanel> </Window> MainWindow.xaml.cs: using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Windows; using System.Windows.Data; namespace ConverterProblem { public class LongDateConverter : IValueConverter { public object Convert(object value,Type targetType,object parameter,CultureInfo culture) { if (value == null) { Debug.WriteLine("In converter: null"); return "null"; } Debug.WriteLine("In converter: " + value.GetType().ToString()); if (value.GetType() == typeof(MainWindowViewModel)) return "viewmodel"; return ((DataModel)value).Date.ToLongDateString(); } public object ConvertBack(object value,CultureInfo culture) { return null; } } public class DataModel { public string Name { get; set; } public DateTime Date { get; set; } } public class MainWindowViewModel : INotifyPropertyChanged { private DataModel _data; private List<DataModel> _dataList; public MainWindowViewModel() { _dataList = new List<DataModel> { new DataModel { Date = DateTime.Now,Name = "John" },new DataModel { Date = DateTime.Now.AddDays(50),Name = "Sue" } }; } public DataModel Data { get { return _data; } set { if (_data == value) return; _data = value; RaisePropertyChanged("Data"); } } public List<DataModel> DataList { get { return _dataList; } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler(this,new PropertyChangedEventArgs(propertyName)); } } } public partial class MainWindow : Window { private MainWindowViewModel _viewModel; public MainWindow() { _viewModel = new MainWindowViewModel(); DataContext = _viewModel; InitializeComponent(); } } } 解决方法
问题是您在为TextBlock设置DataContext之前已绑定了Text依赖项.
XAML文件被编译成BAML,在应用程序运行时,它由BAML通过XAMLLoader加载,它从上到下解析XAML并相应地设置DP的值. 因为,首先遇到Text DP,所以它会尝试首先设置它的值,并且TextBlock尚未设置DataContext,因此它将继承其DataContext设置为MainWindowViewModel的父窗口.因此,您会在转换器中看到MainWindowViewModel.并且当设置DataContext时,将根据新的DataContext重新评估所有DP的绑定. 将您的XAML替换为此,您将看到MainWindowViewModel将不再打印: <TextBlock DataContext="{Binding Data}" Text="{Binding Converter={StaticResource longDateConverter}}" /> 输出: In converter: null In converter: ConverterProblem.DataModel (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |