2

我有一个相当混乱的情况:

我打开一个对话框,显示一个INotifyDataErrorInfo立即返回错误的视图(当文本字段不为空时),我看到红色边框错误通知器:

开幕#1:

首次开业

我什么都不做并关闭窗口,然后再次单击打开按钮:

开幕#2:

第二次开幕

有没有搞错?我检查了错误标志,它已设置。当我删除文本并写回内容时,错误边框会重新出现,因为错误条件会检查string empty? error: no error

这是一个小的复制案例:

编辑:我添加了 ViewModel,它在每个节目中创建,导致 INCP 更改事件

主窗口.xaml.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;

namespace LayoutBreakerMinimal
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonBase_OnClick( object sender, RoutedEventArgs e )
        {
            var w = new Window();
            var v = Resources["OneInstanceView"] as View; // new View(); <-- would work
            w.Content = v;
            v.DataContext = new ViewModel();
            w.ShowDialog();
        }
    }


    public partial class View : UserControl
    {
        public View()
        {
            InitializeComponent();
        }
    }


    public partial class ViewModel : INotifyDataErrorInfo, INotifyPropertyChanged
    {
        private string _myTextField;

        public ViewModel()
        {
            MyTextField = "Error field";
        }

        public string MyTextField
        {
            get { return _myTextField; }
            set
            {
                _myTextField = value;
                OnPropertyChanged();
                if ( ErrorsChanged != null ) ErrorsChanged( this, new DataErrorsChangedEventArgs( "MyTextField" ) );
            }
        }

        public IEnumerable GetErrors( string propertyName )
        {
            yield return "Field is null";
        }

        public bool HasErrors
        {
            get { return MyTextField != ""; }
        }

        public event EventHandler< DataErrorsChangedEventArgs > ErrorsChanged;

        protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
        {
            var handler = PropertyChanged;
            if ( handler != null ) handler( this, new PropertyChangedEventArgs( propertyName ) );
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

主窗口.xaml

<Window x:Class="LayoutBreakerMinimal.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:layoutBreakerMinimal="clr-namespace:LayoutBreakerMinimal"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <layoutBreakerMinimal:View x:Key="OneInstanceView" />
    </Window.Resources>
    <Grid>

        <Button Click="ButtonBase_OnClick" Margin="40">Open Dialog, then open it again</Button>

    </Grid>
</Window>

查看.xaml

<UserControl x:Class="LayoutBreakerMinimal.View"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
 <StackPanel>
    <TextBox Text="{Binding MyTextField, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True}" Height="30" Width="100"></TextBox>
    <Label Content="{Binding HasErrors}" Height="30" Width="100"></Label>
 </StackPanel>
</UserControl>

我无法理解为什么边界会消失。

我发现:如果我每次都创建新视图(而不是单个资源实例),那么每次从一开始就可以使用红色边框。

我测试了将其移动INotifyDataErrorInfo到一个单独的ViewModel中,每次 new 时都会实例化 -> 不走运。

编辑 2:我在视图中添加了 HasError 标签以指示它一直显示错误

4

1 回答 1

1

解决方案:

添加x:Shared="False"如下所示:我已经测试了修复程序,它按预期工作。

<Window.Resources>
        <layoutBreakerMinimal:View x:Key="OneInstanceView" x:Shared="False" />
</Window.Resources>

When x:Shared="False",修改 WPF 资源检索行为,以便对属性资源的请求为每个请求创建一个新实例,而不是为所有请求共享同一个实例。

这是修改后的MainWindow.xaml

<Window x:Class="LayoutBreakerMinimal.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:layoutBreakerMinimal="clr-namespace:LayoutBreakerMinimal"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <layoutBreakerMinimal:View x:Key="OneInstanceView" x:Shared="False" />
    </Window.Resources>

    <Grid>
        <Button Click="ButtonBase_OnClick" Margin="40">Open Dialog, then open it again</Button>
    </Grid>
</Window>
于 2015-02-04T15:07:37.117 回答