Visual Studio 2015 Design View crashes (XDesProc.e

2019-09-18 04:58发布

I have a simple custom control derived from TextBox and used it like that:

<c:MyTextBox Text="Hello World" />
<c:MyTextBox Text="{Binding TextInViewModel}"/>

The first usage works. The one with the databinding doesn't! The design view process (XDesProc.exe) crashes and comes up with:

System.NullReferenceException
Object reference not set to an instance of an object.
  at System.Windows.Controls.TextBoxView.System.Windows.Documents.ITextView.Validate(ITextPointer position)
  at System.Windows.Documents.TextPointer.System.Windows.Documents.ITextPointer.ValidateLayout()
  at System.Windows.Documents.TextSelection.System.Windows.Documents.ITextRange.NotifyChanged(Boolean disableScroll, Boolean skipEvents)
  at System.Windows.Documents.TextRangeBase.EndChange(ITextRange thisRange, Boolean disableScroll, Boolean skipEvents)
  at System.Windows.Documents.TextRange.System.Windows.Documents.ITextRange.EndChange(Boolean disableScroll, Boolean skipEvents)
  at System.Windows.Documents.TextRange.ChangeBlock.System.IDisposable.Dispose()
  at System.Windows.Controls.TextBox.OnTextPropertyChanged(String oldText, String newText)
  at System.Windows.Controls.TextBox.OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
  at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
  at System.Windows.Controls.TextBox.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
  at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
  at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
  at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
  at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
  at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
  at System.Windows.Data.BindingExpression.Activate(Object item)
  at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
  at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
  at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
  at MS.Internal.Data.DataBindEngine.Run(Object arg)
  at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
  at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
  at System.Windows.Threading.DispatcherOperation.InvokeImpl()
  at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
  at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
  at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
  at System.Windows.Threading.DispatcherOperation.Invoke()
  at System.Windows.Threading.Dispatcher.ProcessQueue()
  at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
  at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
  at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
  at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
  at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
  at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
  at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
  at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
  at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
  at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
  at System.Windows.Application.RunDispatcher(Object ignore)
  at System.Windows.Application.RunInternal(Window window)
  at System.Windows.Application.Run(Window window)
  at Microsoft.VisualStudio.DesignTools.DesignerContract.Isolation.DesignerProcess.RunApplication()
  at Microsoft.VisualStudio.DesignTools.DesignerContract.Isolation.DesignerProcess.<>c__DisplayClass5_0.<Main>b__0()
  at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
  at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
  at System.Threading.ThreadHelper.ThreadStart()

Even if the bound property is a stupid auto property like the following, it doesn't work:

public class MyViewModel
{
    public string TextInViewModel { get; set; } = "Simple Property";
}

Debugging XDesProc.exe didn't help. Any other hints?


UPDATE (the complete story):

I implemented a MyBorder control to provide a label for several custom controls like MyTextBox:

<c:MyTextBox Text="Static Text" c:MyBorder.Label="It works :-)" />
<c:MyTextBox Text="{Binding TextInViewModel}" c:MyBorder.Label="It works not :-(" />

How it should look like at design time (at runtime it works perfectly!): The TextBoxes work perfectly at runtime

MyTextBox.cs:

public class MyTextBox : TextBox
{
    static MyTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(typeof(MyTextBox)));
    }
}

MyTextBox.xaml merged into Generic.xaml:

<Style TargetType="{x:Type c:MyTextBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type c:MyTextBox}">
                <c:MyBorder x:Name="Border"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            Foreground="{TemplateBinding Foreground}"
                            IsEnabled="{TemplateBinding IsEnabled}"
                            Label="{Binding (c:MyBorder.Label), RelativeSource={RelativeSource TemplatedParent}}">
                    <ScrollViewer x:Name="PART_ContentHost" Padding="0" />
                </c:MyBorder>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

MyBorder.cs:

[ContentProperty(nameof(Content))]
public class MyBorder : Control
{
    static MyBorder()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyBorder), new FrameworkPropertyMetadata(typeof(MyBorder)));
    }

    public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(UIElement), typeof(MyBorder), new PropertyMetadata(default(UIElement)));

    public UIElement Content
    {
        get { return (UIElement)GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }

    public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(MyBorder), new PropertyMetadata(string.Empty) { CoerceValueCallback = CoerceString });

    public static object CoerceString(DependencyObject d, object value)
    {
        return value ?? string.Empty;
    }

    public string Label
    {
        get { return (string)GetValue(LabelProperty); }
        set { SetValue(LabelProperty, value); }
    }

    public static void SetLabel(DependencyObject element, string value)
    {
        element.SetValue(LabelProperty, value);
    }

    public static string GetLabel(DependencyObject element)
    {
        return (string)element.GetValue(LabelProperty);
    }
}

MyBorder.xaml merged into Generic.xaml:

<Style TargetType="{x:Type c:MyBorder}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type c:MyBorder}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <!-- Label. -->
                    <Border Padding="3,0" Margin="0,-16,0,0" HorizontalAlignment="Right"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="White">
                        <TextBlock Foreground="Black" Text="{TemplateBinding Label}" />
                    </Border>
                    <!-- Content inside Border. -->
                    <Border Grid.Row="1"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}">
                        <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Stretch" />
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

0条回答
登录 后发表回答