c# – 了解WPF数据绑定和值转换器交互

前端之家收集整理的这篇文章主要介绍了c# – 了解WPF数据绑定和值转换器交互前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图了解下面简化的repro代码背后的实际情况.

我有一个单独的Window,其中ListBox和TextBlock绑定在一起(即master – > detail).然后我有一个带有几个属性viewmodel – 一个字符串和一个日期.在这个日期,我实现了一个值转换器(LongDateConverter).

我在代码中有几个Debug.WriteLine()调用,导致以下输出

>启动应用

>在转换器中:ConverterProblem.MainWindowviewmodel
>在转换器中:null

>单击列表框中的两个项目之一

>在转换器中: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

猜你在找的C#相关文章