相关文章推荐
坚强的蘑菇  ·  理解ASP.NET Core - ...·  6 月前    · 
强健的烤面包  ·  Apache ...·  11 月前    · 
酷酷的蜡烛  ·  Android ...·  11 月前    · 
听话的硬盘  ·  首期“Happy ...·  12 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Setting the Attached Property during DataContextChanged event erases the binding content at ViewModel

Ask Question

I found that if I set the the Attached Property during DataContextChanged event, then the binding content at the ViewModel will be erased.

Here is the code sample:

App.xaml

<Application x:Class="DataContextChanged.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:DataContextChanged"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ResourceDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

ResourceDitionary.xaml

<DataTemplate DataType="{x:Type local:SubControlVM}">
    <local:SubControl
       local:AttachedBehaviors.Exporter="{Binding ExtraProperty, Mode=OneWayToSource}"
</DataTemplate>

MainWindow.xaml

<Window x:Class="DataContextChanged.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataContextChanged"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <ContentControl Content="{Binding SubControlVM}" />
</Window>

SubControl.xaml

<UserControl x:Class="DataContextChanged.SubControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DataContextChanged"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Label Content="{Binding ExtraProperty}" Background="AliceBlue"/>
</UserControl>

SubControl.xaml.cs

public partial class SubControl : UserControl
    public SubControl()
        InitializeComponent();
        Loaded += OnLoaded;
        DataContextChanged += OnDataContextChanged;
    private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        AttachedBehaviors.SetExporter(this, 420);  //setting this erases the VM.ExtraProperty and makes it 0
        // var vm = e.NewValue as SubControlVM; //neither this works
        // if(vm!=null)
        //    vm.ExtraProperty = 420;
        //  }
    private void OnLoaded(object sender, RoutedEventArgs e)
        //AttachedBehaviors.SetExporter(this, 42);  //setting this at onLoaded Event updates the VM.ExtraProperty successfully to 42.

SubControlVM

public class SubControlVM : INotifyPropertyChanged
    private double _extraProperty;
    public double ExtraProperty
        get { return _extraProperty; }
            _extraProperty = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ExtraProperty)));
    public SubControlVM()
        ExtraProperty = 1;
    public event PropertyChangedEventHandler PropertyChanged;

MainWindowVM

public class MainWindowVM:INotifyPropertyChanged
    private SubControlVM _subControlVM;
    public SubControlVM SubControlVM
        get { return _subControlVM; }
            _subControlVM = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SubControlVM)));
    public MainWindowVM()
        SubControlVM = new SubControlVM();
    public event PropertyChangedEventHandler PropertyChanged;

AttachedBehavior.cs

public static class AttachedBehaviors
    public static readonly DependencyProperty ExporterProperty =
       DependencyProperty.RegisterAttached("Exporter", typeof(double), typeof(AttachedBehaviors));
    public static double GetExporter(DependencyObject obj)
        return (double)obj.GetValue(ExporterProperty);
    public static void SetExporter(DependencyObject obj, double value)
        obj.SetValue(ExporterProperty, value);

As noted above, if the AttachedBehaviors.SetExporter(this, 42) is done inside the OnLoaded event, then the VM.ExtraProperty is updated successfully, but if it is done inside the DataContextChanged event, then VM.ExtraProperty will be set to 0.

Even if I try to set the VM.ExtraProperty directly inside the DataContextChanged event, it will also get reset back to default value (0).

Why is this so? If I really have to set the VM.ExtraProperty during the DataContextChanged time and not OnLoaded time, then how can I make it to work?

sorry for trying to help, and thanks for the downvote, i delete my project again, good luck – Charles Dec 13, 2019 at 2:14 is the ExporterProperty always reset to 0 after the DataContextChanged no matter what value was there before? – chviLadislav Dec 13, 2019 at 8:14 @chviLadislav, as long as if I set the attached property during DataContextChanged, then the VM value will be reset to 0. – Graviton Dec 13, 2019 at 8:47

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.