I’m banging my head on my desk with this binding error.. I have checked several of the postings for the BindingExpression
path error and cannot see anything that works with my situation.
Anyway, I have a custom control called IncrementingTextBox
. I am trying to disable it whenever the user ‘checks’ the CheckBox
above it.
I have a binding on the CheckBox
IsChecked
property that is working fine and is firing when it is supposed to. It is correctly setting the UseSensorLength
property on the ConfigurationModel.
However, the binding on the IncrementingTextBox
IsEnabled
property is causing a BindingExpression
path error and so doesn’t update at all.
As a test, I tried in the code behind to enable and disable the control and it works just fine, but I can’t seem to get the Binding to work on it.
Here is a snippet from my xaml:
...
DataContext="{Binding RelativeSource={RelativeSource Self}}"
...
...
<CheckBox Content="Use Sensor Length" Margin="30,6,0,0"
IsChecked="{Binding ConfigurationModel.UseSensorLength, Mode=TwoWay}"/>
<local:IncrementingTextBox x:Name="video_length_textbox" Margin="0,0,0,5"
IsTextEnabled="False"
IsEnabled="{Binding ConfigurationModel.DontUseSensorLength}"
ValueChanged="VideoEventValueChanged"/>
And Here is a snippet from my ConfigurationModel:
public bool DontUseSensorLength
{
get { return !UseSensorLength; }
}
public bool UseSensorLength
{
get { return _useSensorLength; }
set
{
_useSensorLength = value;
OnPropertyChanged("UseSensorLength");
OnPropertyChanged("DontUseSensorLength");
}
}
Here is the error message I am getting in my output window when running the app:
System.Windows.Data Error: 40 : BindingExpression path error:
‘ConfigurationModel’ property not found on ‘object’
»IncrementingTextBox’ (Name=’video_length_textbox’)’.
BindingExpression:Path=ConfigurationModel.DontUseSensorLength;
DataItem=’IncrementingTextBox’ (Name=’video_length_textbox’); target
element is ‘IncrementingTextBox’ (Name=’video_length_textbox’); target
property is ‘IsEnabled’ (type ‘Boolean’)
Remember, the ‘UseSensorLength’ property binding is working fine, but the ‘DontUseSensorLength’ binding is causing the above ‘BindingExpression path error’.
Greetings;
I’m having difficulty using WPF’s support for Data Binding a generic List<> instance to a Read-Only DataGrid inside a Window. To setup the Data Binding, I have the following in place in the code:
1.) I set the Window’s DataContext to a reference type of FormattedStackTrace exposed as a public property named StackTrace. The DataContext is set in the Window’s class constructor in C# as follows:
public CallStackDialog(Window owner, FormattedStackTrace stackTrace) { InitializeComponent(); this.Owner = owner; StackTrace = stackTrace; DataContext = StackTrace; return; }
The instance of StackTrace is non-null, and I can access and view all of its property members through the StackTrace property as expected. Likewise, the Window’s DataContext is a non-null value.
2.) The StackTrace property is implemented in the same window class as follows:
private FormattedStackTrace formattedStackTrace; public FormattedStackTrace StackTrace { get { return formattedStackTrace; } set { formattedStackTrace = value; NotifyPropertyChanged("StackTrace"); } }
3.) The FormattedStackTrace class contains an instance of List<OrderedCall> as an auto property named OrderedStackTrace. I am trying to bind this collection as the ItemsSource for the DataGrid in the window. The relative members of the FormattedStackTrace,
which is the backing reference type for the Window’s DataContext, is as follows:
public class FormattedStackTrace { #region FormattedStackTrace Class Data Members & Auto-Properties private StackFrame[] sourceStackFrame; public MethodBase CallingMethod { get; private set; } public List<OrderedCall> OrderedStackTrace { get; private set; } #endregion }
OrderedStackTrace is a List<OrderedCall>, where each List member is an instance of the following structure:
public struct OrderedCall { public int Call; public string Method; };
At the point where the DataContext is set inside the parent Window’s class constructor, the OrderedStackTrace property is correct, in that it contains the expected number of OrderedCall instance values, and they can be viewed without issue inside any of the
Debugging tabs inside Visual Studio 2010, or inside the IDE’s Immediate Window:
? StackTrace.OrderedStackTrace == null
false
? StackTrace.OrderedStackTrace.Count
40
? StackTrace.OrderedStackTrace[39]
{WPFEventHandling.OrderedCall}
Call: 40
Method: «WPFEventHandling.MainWindow.OnMousePointerEnteredButton(Object sender, MouseEventArgs e)»
4.) The DataGrid inside the Window I’m trying to bind to, StackTraceDataGrid, which is read only, is implemented in XAML as follows:
<DataGrid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Name="StackTraceDataGrid" IsReadOnly="True" AutoGenerateColumns="False" Margin="10" ItemsSource="StackTrace.OrderedStackTrace"> <DataGrid.Columns> <DataGridTextColumn Header="Offest" Binding="{Binding Call}" Width="60"> </DataGridTextColumn> <DataGridTextColumn Header="Method" Binding="{Binding Method}" Width="*"> </DataGridTextColumn> </DataGrid.Columns> </DataGrid>
When I build the solution containing this Window and the child StackTraceDataGrid control, there are no errors nor compiler warnings. When I bring up the parent window that contains StakTraceDataGrid, the DataGrid and the two Text Columns, Offset and
Method, are rendered and formatted as expected, but each row in the DataGrid is empty. When the Window is brought up, the following set of runtime messages appear for each pair of OrderedCall member values in each column for each row:
System.Windows.Data Error: 40 : BindingExpression path error: ‘Call’ property not found on ‘object’ »Char’ (HashCode=7471218)’. BindingExpression:Path=Call; DataItem=’Char’ (HashCode=7471218); target element is ‘TextBlock’ (Name=»); target property is ‘Text’
(type ‘String’)
System.Windows.Data Error: 40 : BindingExpression path error: ‘Method’ property not found on ‘object’ »Char’ (HashCode=7471218)’. BindingExpression:Path=Method; DataItem=’Char’ (HashCode=7471218); target element is ‘TextBlock’ (Name=»); target property is
‘Text’ (type ‘String’)
As far as I can tell, I think that my problem may lie in how I’ve defined the ItemsSource property for the DataGrid, and the Binding Path for each column for each instance of OrderedCall as I would like to have displayed in each row of the Grid.
I would really appreciate any corrections on how to resolve the BindingExpression path errors I’m seeing at runtime, as well as any background informatio on what each DataGrid Column is expecting for a Binding Path for each item in each row of the DataGrid.
Thank you in advance for your time and help, and I look forward to hearing from you soon.
Igorian 1 / 1 / 0 Регистрация: 22.11.2013 Сообщений: 19 |
||||||||||||||||||||||||
1 |
||||||||||||||||||||||||
03.11.2015, 12:21. Показов 7168. Ответов 8 Метки wpf (Все метки)
Здравствуйте, у меня есть Главное окно, есть 2 контрола. В 1-ом контроле у меня listBox, во втором label, соединяю я их в MainWindow. Так вот, мне нужно, чтобы в главном окне я нажимал на listBox и у меня имя, выбранное в ListBox-е отображалось в Label. Список выводит, но при нажатии ничего не происходит, а пишется ошибка Кто-нибудь помогите, плз! 1.Главное окно —
xaml к MainWindow
,
,
,
,
__________________
0 |
amarf Жуткая тВарЬ 389 / 325 / 134 Регистрация: 06.02.2015 Сообщений: 960 Записей в блоге: 1 |
||||
03.11.2015, 14:19 |
2 |
|||
1 |
1 / 1 / 0 Регистрация: 22.11.2013 Сообщений: 19 |
|
03.11.2015, 23:09 [ТС] |
3 |
Неа, не помогает, теперь вылетает ошибка -> System.Windows.Data Error: 40 : BindingExpression path error: ‘name’ property not found on ‘object’ »MainWindow’ (Name=»)’. BindingExpression:Path=name; DataItem=’MainWindow’ (Name=»); target element is ‘UserControl1′ (Name=’me’); target property is ‘SelectedName’ (type ‘String’)
0 |
Жуткая тВарЬ 389 / 325 / 134 Регистрация: 06.02.2015 Сообщений: 960 Записей в блоге: 1 |
|
04.11.2015, 20:56 |
4 |
Так перенесите свойство в клпасс окна… Вы вообще про привязку читали? Добавлено через 6 минут
1 |
Igorian 1 / 1 / 0 Регистрация: 22.11.2013 Сообщений: 19 |
||||||||
05.11.2015, 18:57 [ТС] |
5 |
|||||||
Извиняюсь, но я новичок в этом деле и пытаюсь понять, как это работает. Вот написал ->
Ошибка исчезла, но проблема с передачей данных осталась. Т.е. если нажимаешь на строку таблицы 1Контрола, ничего не происходит во 2ом Контроле. А как тогда должна инфа передаваться в этот 2ой контрол ->
Изначально я передавал данные из SelectedName(1Контрол) в name (Главного окна), затем из name(Главного окна) передавалось в DisplayName(2го Контрола). А теперь чего делать? Сейчас из SelectedName(1Контрол) в DataContext.name (Главного окна), затем из … что куда должно передаться, чтоб отобразилось во 2омКонтроле?
0 |
Жуткая тВарЬ 389 / 325 / 134 Регистрация: 06.02.2015 Сообщений: 960 Записей в блоге: 1 |
|
05.11.2015, 20:20 |
6 |
Igorian, Вам быпочитать про mvvm, принципы построения слобосвязанных приложений и много чего еще, но это кучу времени потратите, но оно тогг стоит. Так, что если есть время то начните чтение с внедрения зависимостей ибо на этом принципе и паттерне стратегия уйма всего устроено… Ну естественно по wpf тоже надо читать, но не так много… Я могу Вам накидать пример под Вашу задачу, только опишите что хотите получить от работы программы, применение юзерконтролов у вас не обоснованно и не нужно
1 |
1 / 1 / 0 Регистрация: 22.11.2013 Сообщений: 19 |
|
05.11.2015, 21:30 [ТС] |
7 |
Спасибо за инфу о том, что нужно почитать. Это я обязательно сделаю. Насчет необоснованных контролов — да, я согласен, в этом примере они не нужны, но у меня есть приложение, в котором я использую avalonDock. Там нужны контролы, которые будут подгружаться в качестве отдельных окон и которые будут использоваться в разных местах. А этот пример я взял для того, чтобы понять, как это дело работает. Я делал все это дело без viewModel, все получилось, а вот когда я использую viewModel, вот ничего и не получается. Задача у меня такая — Есть 2 Контрола: — 1Контрол — Таблица listBox/ListView(В ней выбирается строка для отображения во втором контроле), 2Контрол — Label, в который записывается просто имя , выбранное из первого контрола. И все это связано через MainWindow. Потом я вместо имени буду данные из базы закидывать и подружать
0 |
Жуткая тВарЬ 389 / 325 / 134 Регистрация: 06.02.2015 Сообщений: 960 Записей в блоге: 1 |
|
06.11.2015, 10:17 |
8 |
В общем накидал пример, единственное, что я решил сделать с использованием аггрегатора событий из библиотеки призм (короче надо устанавливать через Nuget пакет Prism.PubSubEvents) — зато он убирает кучу всякой хрени в которой можно запутаться (в частности излишнюю управляющую вьюмодель и колбэки с подписками) Так же прощу обратить внимание, что есть специальный класс Boot в котором назначаются вьюмодели для наших контролов — ТАК ДЕЛАТЬ НЕЛЬЗЯ — но поскольку я не стал нагружать проект еще и контейнером внедрения зависимости, мне показалось, что такой подход будет понятнее… AggregateMVVM.zip П.С. На самом деле «по настоящему» все делается немножко сложнее (и в тоже время легче если знаешь материал), но для этого надо знать хотя бы про Внедрение зависимостей в .Net и несколько паттернов
1 |
1 / 1 / 0 Регистрация: 22.11.2013 Сообщений: 19 |
|
07.11.2015, 10:04 [ТС] |
9 |
amarf, Спасибо огромное за написанный вами пример!
0 |
Hello,
I have changed the title of my question because I don’t understand this error in the binding with the view.I know how to read it,but i don’t understand it’s cause or how should I change the syntax for it in a proper solution.This is my method for storing values:
View-Model:
public void SaveTeacher(object param) { using (DatabaseStudentsEntitiesLastStand db = new DatabaseStudentsEntitiesLastStand()) { RegisterTeacher t = new RegisterTeacher(); if (isChecked == true || t.CourseName != null) { t.CourseName = courseName; } t.SNTeacher = SNTeacher; t.UserName = _UserName; t.pwd = pwd; t.fullName = fullName; t.education = education; db.RegisterTeachers.Attach(t); try { db.SaveChanges(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } }
This is the isChecked property:
private bool isChecked; public bool IsChecked { get { return IsChecked; } set { if (isChecked != value) { isChecked = value; NotifyOnPropertyChange("IsChecked"); } } } private DelegateCommand checkCommand; public DelegateCommand CheckCommand { get { if (checkCommand == null) checkCommand = new DelegateCommand(SaveTeacher, null); return checkCommand; } set { checkCommand = value; NotifyOnPropertyChange("CheckCommand"); } }
This is the binding with the view:
<Button Content="Submit" Command="{Binding SaveCommand}" HorizontalAlignment="Left" Margin="517,98.4,0,0" Grid.Row="2" VerticalAlignment="Top" Width="110" Height="40"/> <Button Content="Cancel" HorizontalAlignment="Left" Margin="361,98.4,0,0" Grid.Row="2" VerticalAlignment="Top" Width="111" Height="40"/> <ListBox HorizontalAlignment="Left" Name="coursesList" Height="240" Margin="418,13.2,0,0" Grid.Row="1" VerticalAlignment="Top" Width="225" Grid.RowSpan="2" ItemsSource="{Binding Courses}" > <ListBox.ItemTemplate> <DataTemplate> <CheckBox x:Name="CheckBoxCourses" Click="CheckBoxCourses_Click" IsChecked="{Binding Path=IsChecked,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Command="{Binding CheckCommand,Mode=TwoWay}" Content="{Binding Path=courseName,Mode=TwoWay}" Margin="0"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
This is the Checked event:
private void CheckBoxCourses_Checked(object sender, RoutedEventArgs e) { var checkbox = sender as CheckBox; if(checkbox!=null) { checkbox.IsChecked =true; } }
What I have tried:
This is the entire error:
System.Windows.Data Error: 40 : BindingExpression path error: 'IsSelected' property not found on 'object' ''Cours' (HashCode=44335814)'. BindingExpression:Path=IsSelected; DataItem='Cours' (HashCode=44335814); target element is 'CheckBox' (Name=''); target property is 'IsChecked' (type 'Nullable`1')
I have tried multiple solutions with delegatecommand,selecteditem in the listbox and IsSelected property,read-only properties,nothing is working.Since I have tried many approaches,I have moved the property IsChecked from the view-model to the model class named «Cours» along with NotifyPropertyChanged(so it basically looks like the one I have in my example,only that it is in the model,not vm).Can someone please tell me what would be the problem based on this error?Please notify me if you need certain lines of code.
This article covers many techniques you can use to troubleshoot and debug your WPF application, including binding errors, exception handling, inspecting the VisualTree and logging.
Table of Contents
- Introduction
- Binding Errors
- 1. Changing Trace Level for All in Options
- 2. Changing Trace Level on a Specific Binding
- WPF Tree Visualizer
- Other inspection tools
- Debuging Your Code
- Inner Exceptions
- Unhandled Exceptions
- Application.DispatcherUnhandledException
- AppDomain.CurrentDomain.UnhandledException
- TaskScheduler.UnobservedTaskException
- The catch-all Unhandled Handler!
- Drilling down to include the Inner Exceptions
- Commenting Out and Binary Chopping
- Is It Reproducable?
- Logging
- Logging Level
- Repository Choice
- Why Reinvent the Wheel
- Log4Net
- ELMAH
- NLog
- NuGet
- See Also
- Community Resources
Introduction
Windows Presentation Foundation (WPF) is a joy to develop rich user experiences with. Animations, bindings, reskinnable codeless interfaces, all backed up with traditional .Net programming all make for a very rapid development cycle. However, when something
goes wrong in that autogenerated super-sexy front-end, it is not always clear where the problem is.
This article will cover some of the methods for analyzing your WPF application, troubleshooting issues, and debugging seemingly obscure errors.
↑
Return to Top
Binding Errors
When an error occurs in the binding framework, the notification is usually «silent», in that is doesn’t pop up an error dialog to the user. The error is instead displayed in the
Output Window of Visual Studio. Although the errors seem obscure at first, there are only a few common ones and they are quite helpful messages.
Below are some typical errors and an explanation for each.
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.UserControl', AncestorLevel='1''. BindingExpression:Path=PartIds; DataItem=null; target element is 'ComboBox'
(Name=''); target property is 'ItemsSource' (type 'IEnumerable')
This is a ComboBox inside a DataGridTemplateColumn. I am binding its ItemsSource to a property called PartIds.
It is erroring when looking for the binding source, in other words the physical object to find the property on.
In this example, the error was because the source is a Window, not a UserControl.
"System.Windows.Data Error: 40 : BindingExpression path error: 'MyStringOptionz' property not found on 'object' ''MainWindow' (Name='Window')'. BindingExpression:Path=MyStringOptionz; DataItem='MainWindow' (Name='Window'); target element is 'ComboBox'
(Name=''); target property is 'ItemsSource' (type 'IEnumerable')"
This is when the property name in the binding expression is wrong, or the property does not exist in the source object.
In this example, the property name was misspelled with a ‘z’.
Sometimes you will need a more detailed debugging output for binding. There are two ways to do this.
1. Changing Trace Level for All in Options
Click the Visual Studio menu Tools / Options, then open
Debugging and Output Window. In there you can change the
DataBinding output settings to Verbose or
All.
(click to enlarge)
2. Changing Trace Level on a Specific Binding
If you increase the trace level that way, you will get a WHOLE LOAD of messages for everything. Far better to target the specific binding where the error is. To do this, you can call on an Attached Property PresentationSources.TraceLevel and set it for just
the one binding.
<
ComboBox
ItemsSource
=
"{Binding PartIdz,
PresentationTraceSources.TraceLevel=High, RelativeSource={RelativeSource AncestorType=Window}}"
. . . />
For more information on the Trace Levels and what they represent,
read here.
↑
Return to Top
WPF Tree Visualizer
The WPF Tree Visualizer comes built into Visual Studio, and is an essential tool to know about.
With it, you can break into the Visual Tree and inspect the actual generated elements and their properties.
To use a Visualizer, you click on the magnifying glass next to a variable name in
DataTips, a Watch window, or in the
Autos, Locals, or
Quick Watch window.
If you are visualizing a string object for example, you get a big grey text window. However, if you visualize a FrameworkElement, you get the WPF Tree Visualizer.
(click to enlarge)
For a Quick Start on how to use the WPF TV, try this :
Debugging WPF — WPF Tree Visualizer + Helper Class
It also supplies a handy Attached Property you can drop in anywhere, without messing your code.
The WPF Tree Visualizer is great for inspecting the VisualTree, but if you want to
change any of the properties, you have to look at the «Locals» tab, as shown below.
(click to enlarge)
Other inspection tools
WPF Tree Visualizer is usually enough for the experienced developer to find the problem, however there are plenty of tools around if you prefer to defer.
- WPF Inspector
- UI Spy (in Microsoft Windows SDK)
- Snoop
- XamlIT
- Mole
- Pistachio
↑
Return to Top
Debuging Your Code
Apart from the WPF Tree Visualiser, the debugger in WPF applications is the main way to break into your application, trace through and follow program execution to the point of failure.
This is all standard Visual Studio stuff, and I won’t waste time here reproducing what is available elsewhere:
- Debugging in Visual Studio
- Debugging Managed Code
- Debugging, Tracing, and Profiling
↑
Return to Top
Inner Exceptions
When your application raises an exception, and you are debugging in Visual Studio, you get the usual error dialog with the details. However, when the error is a XAML error, it is most frequently buried deeper in the exception details.
Within each exception is an Inner Exception, which is just another exception, but from a layer further down. If XAML throws an error about a missing resource, it re-raises the error as a meaningless «XAML Markup error». When you drill down deeper, you find
what resource the actual error relates to.
Josh Smith wrote best documents the joy of inner exceptions here.
↑
Return to Top
Unhandled Exceptions
It is impossible to protect against every possible fault that could happen, when your application is «out in the wild».
There are however, ways to try and improve on the standard Windows error dialogue, and stack dump, which will help you find the fault.
When an exception is unhandled by your application, there are several Unhandled Exception events that you can tap into and handle.
You can download and test all five handlers here :
Handling Unhandled Exceptions in WPF (The most complete collection of handlers)
Application.DispatcherUnhandledException
This is triggered when the UI thread causes an unhandled exception. You can attach a handler to it either in App.xaml
<
Application
x:Class
=
"MyProject.App"
StartupUri
=
"MainWindow.xaml"
DispatcherUnhandledException
=
"App_DispatcherUnhandledException"
>
<
Application.Resources
/>
</
Application
>
… or App.xaml.cs
namespace
MyProject
{
public
partial
classApp : Application
{
public
App()
{
DispatcherUnhandledException +=
new
System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
What you get in the handler arguments is a standard exception. Handle as you like, preferably write it to a permissions safe file location.
You can also set e.Handled to true if you want to try to overcome the error and move on
void
App_DispatcherUnhandledException(
object
sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
ProcessError(e.Exception);
e.Handled =
true
;
}
Sometimes the error is too severe, and your application still crashes. But at least you have hopefully captured something useful, before it did.
AppDomain.CurrentDomain.UnhandledException
If the error is not on the UI thread, then the previous handler won’t catch it. It is solely for the Dispatcher thread. To capture errors on any other thread, you need this second one.
This handler is attached in the Startup event handler, which can again be hooked into from mark-up:
<
Application
x:Class
=
"UnhandledExceptionHandler.App"
StartupUri
=
"MainWindow.xaml"
Startup
=
"App_Startup"
>
<
Application.Resources
/>
</
Application
>
… or in code:
namespace
MyProject
{
public
partial
classApp : Application
{
public
App()
{
Startup +=
new
StartupEventHandler(App_Startup);
}
void
App_Startup(
object
sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
void
CurrentDomain_UnhandledException(
object
sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject
as
Exception;
ProcessError(exception);
if
(e.IsTerminating)
MessageBox.Show(
"Goodbye world!"
);
}
Notice this uses an ExceptionObject, which is derived from Exception, so we can simply cast it back, for a generic exception handler, as shown below.
Also notice the ExceptionObject has an IsTerminating flag.
TaskScheduler.UnobservedTaskException
This exception happens when a Task has an «unobserved exception», and is about to trigger the «exception escalation policy», which by default
terminates the process.
namespace
MyProject
{
public
partial
classApp : Application
{
public
App()
{
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
Again, we can try to prevent crashing, in this case by calling the e.SetObserved method, which marks the exception as «observed» and prevents exception escalation towards a termination (crash).
void
TaskScheduler_UnobservedTaskException(
object
sender, UnobservedTaskExceptionEventArgs e)
{
ProcessError(e.Exception);
e.SetObserved();
}
The catch-all Unhandled Handler!
Putting those three handlers together, we get the following:
namespace
MyProject
{
public
partial
classApp : Application
{
public
App()
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Startup +=
new
StartupEventHandler(App_Startup);
}
void
App_Startup(
object
sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
In the examples below, I show how to try and mark the exceptions as handled/observed, and continue execution. However, you may just want to close «gracefully», with a polite message, instead of an all-out crash.
One thing is certain, you will probably want a unified way of handling the exceptions, wherever they come from, as shown below.
Drilling down to include the Inner Exceptions
As mentioned before, the real reason for an error could be buried several layers down in Inner Exceptions. The three handlers above shared one error logging method, shown below, which iterates down till there are no more Inner Exceptions.
private
void
ProcessError(Exception exception)
{
var error =
"Exception = "
+ exception.Message;
while
(exception.InnerException !=
null
)
{
exception = exception.InnerException;
error +=
" : Inner Exception = "
+ exception.Message;
}
//This is where you save to file.
MessageBox.Show(error);
}
Early attention to error handling in your application will always help production, because most bugs occur during development.
See Logging below.
↑
Return to Top
Commenting Out and Binary Chopping
If a bug in your application is being particularly hard to find, there may be only one way left to find the culprit. It’s very simple, and is often simply the fastest way to drill down to the offender.
The method is simply to remove (or comment out) sections of your code, or XAML, until you get execution PAST the error.
Then you start replacing parts of the removed code, until you find the exact control or method that is causing the problem.
It is referred to as binary chopping because you cut the code into two, to get past the error, then in two again, replacing half of the removed code, and so on until you get down to the offending code/xaml.
You can comment out huge chunks of your code or markup in Visual Studio with ctrl-k + c, then ctrl-k + u to uncomment. Both functions also available in the edit / advanced menu.
This is one of the advantages of writing your application to the MVVM design pattern. MVVM separates your UI (View) from the business logic supplied by the ViewModel, or the Model itself. This means the View is much more loosely coupled, and there are no
hooks from code-behind, acting directly on controls, like referring to controls by name (x:Name) like MyTextBox.Text = «hello». In MVVM the emphasis is all on the bindings, so commenting out half your XAML just means less binding requests, and commenting out
half your code/properties means more binding errors, but not a crash.
Even an MVVM setup can have problems when you try to comment out half the markup. Controls may be relying on other controls, with direct biding in XAML. So there is always a certain amount of «knock-on» effects that also need commenting out, but experience
often shows it is quite simply a very fast and effective way to find the sinner.
Just make sure you keep a copy of the original file (or have recently committed your code to source control) before such dramatic actions. Just in case you make an edit that looses your comment/cut history
↑
Return to Top
Is It Reproducable?
When you hit a brick wall, many people turn to the
MSDN forums, for help and advice from other developers. Often, just the act of trying to put a problem into words for others to understand is equivalent to having a colleague look over your shoulder, which often catches those obvious «too close to the trees»
kind of mistakes that we all make.
However, if the problem isn’t obvious from your description, you will get a much quicker and accurate response from the forum if you supply a
reproduceable example of your problem in a few code snippets.
Quite often, when you try to reproduce the problem in a new project, you will often find the culpret anyway!
↑
Return to Top
Logging
The other age old method of tracing bugs in your application, both in development and once released, is to keep a log of messages from every notable step of your application.
If your bug is of a composite nature (comprising of several different causes), or developing after several iterations, or at an unknown point, you will need to build a picture of what is happening, before you can even know where to start.
Logging Level
Writing comments and session data to a log file means scattering «WriteToLog» type methods throughout your code. It is therefore common to build a «LogLevel» parameter into your methods, allowing you to control the amount of spam that gets written. In a
published application you would only want to capture critical messages, but with a config file flag or startup parameter that allows you to crank up the debug logging (logging ALL messages), for a client that experiences a bug.
Repository Choice
A log repository can be anything from a text file, to a database. One word of caution however. It is no good logging errors to a database if it was a database connection error. So file based logging for critical errors is strongly advised. Then you simply
have a check method on application startup, for any waiting critical error files, that may have been generated when the application crashed. You can then ‘process’ them (into a database, or send by email) and then delete.
It is as explained, quite simple to create your own logging architecture for your application. The key to success is to START EARLY! Don’t try to strap error handling or logging on later, as it will never be as useful as if you had started from the outset.
Also, the majority of bugs are caused during development anyway, so early attention to error handling and logging may take slightly longer to code, but will help speed up the overall production process.
Why Reinvent the Wheel
You could have a lot of fun building your own error logging framework, that is thread safe and foolproof. Or if you’re pushed for time or more interested in higher things, why not just adopt a tried and tested logging framework. Here are some options, but
you should shop around, as new kids often come on the block.
Log4Net
One of the most established frameworks. «log4net is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that
the problem can be located. With log4net it is possible to enable logging at runtime without modifying the application binary. The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows
that the speed of logging (or rather not logging) is crucial. At the same time, log output can be so voluminous that it quickly becomes overwhelming. One of the distinctive features of log4net is the notion of hierarchical loggers. Using these loggers it is
possible to selectively control which log statements are output at arbitrary granularity. log4net is designed with two distinct goals in mind: speed and flexibility»
ELMAH
A very popular framework. «Stands for Logging Modules and Handlers. An application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications
on a machine, without any need for re-compilation or re-deployment.»
NLog
Newer but 3rd popular «A logging platform for .NET with rich log routing and management capabilities. It can help you produce and manage high-quality logs for your application regardless of its size or complexity.»
NuGet
All of the above frameworks are available through NuGet. If you don’t already have NuGet, it is like an App store for Visual Studio application development. If you want a logging framework, or an MVVM framework, simply open the package manager and search.
Results are listed by popularity. Click to install, and the package gets downloaded and integrated into your current project. That means all the dlls are added and registered, and any supporting files are added to your project. It takes all the pain out of
adding supporting packages to your project. This is a must for all developers. No excuses, get it now!
↑
Return to Top
See Also
- Troubleshooting Portal
- See routed events article
http://code.msdn.microsoft.com/silverlight/WPFSilverlight-Routed-49a16914
↑
Return to Top
Community Resources
- Debugging WPF — WPF Tree Visualizer + Helper Class
- How to: Use the WPF Tree Visualizer
- How to: Display WPF Trace Information
- Trees in WPF
- Breakpoints
- Locals Window
- Threads Window
- Output Window
- Exception.InnerException Property
- Application.DispatcherUnhandledException Event
- AppDomain.UnhandledException Event
- Dispatcher.UnhandledException Event
- Tips on how to debug and learn about WPF
- WPF performance Suite (in Windows SDK)
- UI Spy (in Windows SDK)
- Spy++
- StyleSnooper
- Optimizing WPF Application Performance
- Debugging Tools (.NET Framework)
- Debugging in Visual Studio
- Debugging Managed Code
- Debugging, Tracing, and Profiling
↑
Return to Top
I guess it is the error message that seems having nothing to do with Win Form makes people hesitate to response to your question. The error message looks like somehow related to WPF UI. Also, when you say «… show this in debug», what does «debug» mean? where exactly do you see the error message? A pop-up window in AutoCAD, where you can click either «Detail» to see more error message, or «Continue», which would either let AutoCAD continue. if the error is not that fatal, or let AutoCAD die?
Anyway, if your Form1 is a true win form, regardless the strange error, your code in the CommandMethod is very wrong, in 2 ways:
1. You DO NOT show dialog form (modal view) with Form.ShowDialog() in AutoCAD .NET API add-in. You must use AutoCAD .NET API method
Autodesk.AutoCAD.ApplicationServices.Application.ShowModalDialog[Window]()
2. You DO NOT sandwich all the code (showing the dialog box, and then user may do something to AutoCAD by interacting with the form) with a Transaction and only not commit it (which means whatever user does to AutoCAD would be aborted when you close the dialog form. That is why the line drawn by the button clicking action is not there: it is lost after you close the form. because the outer-most transaction is not commited (thus, aborted automatically).
While letting UI’s event handler (button clicking, in your case) directly interact with AutoCAD isn’t a very good code practice, I think you can live with that for now (as beginner?), thus, the simple fix to your code is to modify the CommandMethed as following:
[CommandMethod("ACADPipe")]
public static void pipe()
{
using (Form1 form1 = new Form1())
{
Application.ShowModalDialog(form1);
}
}
And, in your drawTestLine_Click() method, you might want to add
ed.UpdateScreen()
at the end of the Transaction, if you want the newly created line to be seen without dismissing the dialog box.
I had same problem because class of object from which I was pulling out data didn’t have get; and set; on its properties.
this didn’t work:
public string Name;
but this worked:
public string Name{ get; set; }
I wrote some other SO answer recently about how to read the binding errors so they make more sense. To summarize, add line breaks to your error message on the colons and semi-colons, and read it from the bottom up.
Your error message is:
- System.Windows.Data Error: 40 :
- BindingExpression path error: ‘ConfigurationModel’ property not found on ‘object’ »IncrementingTextBox’ (Name=’video_length_textbox’)’.
- BindingExpression:Path=ConfigurationModel.DontUseSensorLength;
- DataItem=’IncrementingTextBox’ (Name=’video_length_textbox’);
- target element is ‘IncrementingTextBox’ (Name=’video_length_textbox’);
- target property is ‘IsEnabled’ (type ‘Boolean’)
This can be read from the bottom up as:
-
The binding failing is the
IsEnabled
property of an element of typeIncrementingTextBox
(named video_length_textbox). -
The
DataItem
(DataContext
) of the element is an object of typeIncrementingTextBox
named video_length_textbox -
The binding expression it is trying to find is
ConfigurationModel.DontUseSensorLength
-
And the problem the binding is having is that the
ConfigurationModel
property is not found on the data context objectIncrementingTextBox
So your DataContext
for «video_length_textbox» is set to itself, and your IncrementingTextBox
class does not have a public property called ConfigurationModel
Since I don’t see you setting the DataContext
for your IncrementingTextBox
anywhere in your XAML, check out the code for your IncrementingTextBox
class. The most likely case is you are setting the DataContext to itself in either the Constructor
this.DataContext = this;
or the XAML
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Tags:
C#
Wpf
Xaml
Binding
Related
I’m binding an observsable collection of model objects to a data grid. But when I set the binding to the collection, I get a path error to the peoprties.
In debugging this issue, I’ve checked that the public properties in the CustomerModel are correctly named in the DataGrid binding. And also that the collection being returned to the model isn’t empty. I also checked that the data context is set correctly in the View’s code behind.
I think it might be an error due to the way I’ve specified the binding path in the xaml..
The full details of the binding error is as follows, for each field:
System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=FirstName; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='fNameTbx'); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'LastName' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=LastName; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='lNameTbx'); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'Email' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=Email; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='emailTbx'); target property is 'Text' (type 'String')
Could anyone point me in the right direction, in order to debug this further?
DataGrid binding path and source are set as follows:
<DataGrid Name="infogrid"
Grid.Row="0"
Grid.RowSpan="3"
Grid.Column="1"
Grid.ColumnSpan="3"
AutoGenerateColumns="False"
ItemsSource="{Binding Customers}"
SelectedItem="{Binding SelectedCustomer}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Customers.Id}" Header="ID" />
<DataGridTextColumn Binding="{Binding Customers.FirstName}" Header="First Name" />
<DataGridTextColumn Binding="{Binding Customers.LastName}" Header="Last Name" />
<DataGridTextColumn Binding="{Binding Customers.Email}" Header="Email" />
</DataGrid.Columns>
</DataGrid>
The View Model contains an Observable collection of type CustomerModel, called Customers. This is what I’ve set the DataGrid ItemSource to. (I’ve removed other code from VM for readability)
namespace MongoDBApp.ViewModels
{
class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private ICustomerDataService _customerDataService;
public MainViewModel(ICustomerDataService customerDataService)
{
this._customerDataService = customerDataService;
QueryDataFromPersistence();
}
private ObservableCollection<CustomerModel> customers;
public ObservableCollection<CustomerModel> Customers
{
get
{
return customers;
}
set
{
customers = value;
RaisePropertyChanged("Customers");
}
}
private void QueryDataFromPersistence()
{
Customers = _customerDataService.GetAllCustomers().ToObservableCollection();
}
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
And these are the fields that in the CustomerModel, so not sure why the properties are not being found during binding:
public class CustomerModel : INotifyPropertyChanged
{
private ObjectId id;
private string firstName;
private string lastName;
private string email;
[BsonElement]
ObservableCollection<CustomerModel> customers { get; set; }
/// <summary>
/// This attribute is used to map the Id property to the ObjectId in the collection
/// </summary>
[BsonId]
public ObjectId Id { get; set; }
[BsonElement("firstName")]
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
RaisePropertyChanged("FirstName");
}
}
[BsonElement("lastName")]
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
RaisePropertyChanged("LastName");
}
}
[BsonElement("email")]
public string Email
{
get
{
return email;
}
set
{
email = value;
RaisePropertyChanged("Email");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
This is how the data context is set in the View’s code behind:
public partial class MainView : Window
{
private MainViewModel ViewModel { get; set; }
private static ICustomerDataService customerDataService = new CustomerDataService(CustomerRepository.Instance);
public MainView()
{
InitializeComponent();
ViewModel = new MainViewModel(customerDataService);
this.DataContext = ViewModel;
}
}
These binding errors are not related to your DataGrid.
They indicate that you have 3 TextBoxes somewhere of the names fNameTbx
, lNameTbx
, and emailTbx
. A DataGrid does not generate it’s items with a Name property, so it is not the one causing these binding errors.
When trying to read binding errors, it’s best to break them up by semi-colons and read them backwards, as demonstrated here.
For example,
System.Windows.Data Error: 40 : BindingExpression path error: ‘FirstName’ property not found on ‘object’ »MainViewModel’ (HashCode=55615518)’. BindingExpression:Path=FirstName; DataItem=’MainViewModel’ (HashCode=55615518); target element is ‘TextBox’ (Name=’fNameTbx’); target property is ‘Text’ (type ‘String’)
Can also be read as
- target property is ‘Text’ (type ‘String’)
- target element is ‘TextBox’ (Name=’fNameTbx’);
- DataItem=’MainViewModel’ (HashCode=55615518);
- BindingExpression path error: ‘FirstName’ property not found on ‘object’ »MainViewModel’ (HashCode=55615518)’. BindingExpression:Path=FirstName;
Meaning somewhere you have
<TextBox Name="fNameTbx" Text="{Binding FirstName}" />
Where the DataContext
of this TextBox is of type MainViewModel
. And MainViewModel
does not have a property of FirstName
.
I’d recommend searching your project for those names, or you could use a tool like Snoop to debug databindings and DataContext issues at runtime.
Data binding:
Since data bindings are evaluated at runtime, and no exceptions are thrown when they fail, a bad binding can sometimes be very hard to track down. These
problems can occur in several different situations, but a common issue is when you try to bind to a property that doesn’t exist, either because you
remembered its name wrong or because you simply misspelled it. Here’s an example:
<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataBindingDebuggingSample" Height="100" Width="200">
<Grid Margin="10" Name="pnlMain">
<TextBlock Text="{Binding NonExistingProperty, ElementName=pnlMain}" />
</Grid>
</Window>
The Output window
The first place you will want to look is the Visual Studio Output window. It should be at the bottom of your Visual Studio window, or you can activate it
by using the [Ctrl+Alt+O] shortcut. There will be loads of output from the debugger, but somewhere you should find a line like this, when running the above
example:
System.Windows.Data Error: 40 : BindingExpression path error: ‘NonExistingProperty’ property not found on ‘object’ »Grid’ (Name=’pnlMain’)’.
BindingExpression:Path=NonExistingProperty; DataItem=’Grid’ (Name=’pnlMain’); target element is ‘TextBlock’ (Name=»); target property is ‘Text’ (type
‘String’)
This might seem a bit overwhelming, mainly because no linebreaks are used in this long message, but the important part is this:
‘NonExistingProperty’ property not found on ‘object’ »Grid’ (Name=’pnlMain’)’.
It tells you that you have tried to use a property called «NonExistingProperty» on an object of the type Grid, with the name pnlMain. That’s actually
pretty concise and should help you correct the name of the property or bind to the real object, if that’s the problem.
Adjusting the trace level
The above example was easy to fix, because it was clear to WPF what we were trying to do and why it didn’t work. Consider this next example though:
<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataBindingDebuggingSample" Height="100" Width="200">
<Grid Margin="10">
<TextBlock Text="{Binding Title}" />
</Grid>
</Window>
I’m trying to bind to the property «Title», but on which object? As stated in the article on data contexts, WPF will use the DataContext property on the
TextBlock here, which may be inherited down the control hierarchy, but in this example, I forgot to assign a data context. This basically means that I’m
trying to get a property on a NULL object. WPF will gather that this might be a perfectly valid binding, but that the object just hasn’t been initialized
yet, and therefore it won’t complain about it. If you run this example and look in the Output window, you won’t see any binding errors.
However, for the cases where this is not the behavior that you’re expecting, there is a way to force WPF into telling you about all the binding problems it
runs into. It can be done by setting the TraceLevel on the PresentationTraceSources object, which can be found in the System.Diagnostics namespace:
<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="DataBindingDebuggingSample" Height="100" Width="200">
<Grid Margin="10">
<TextBlock Text="{Binding Title, diag:PresentationTraceSources.TraceLevel=High}" />
</Grid>
</Window>
Notice that I have added a reference to the System.Diagnostics namespace in the top, and then used the property on the binding. WPF will now give you loads
of information about this specific binding in the Output window:
System.Windows.Data Warning: 55 : Created BindingExpression (hash=2902278) for Binding (hash=52760599)
System.Windows.Data Warning: 57 : Path: 'Title'
System.Windows.Data Warning: 59 : BindingExpression (hash=2902278): Default mode resolved to OneWay
System.Windows.Data Warning: 60 : BindingExpression (hash=2902278): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 61 : BindingExpression (hash=2902278): Attach to System.Windows.Controls.TextBlock.Text (hash=18876224)
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 64 : BindingExpression (hash=2902278): Resolve source deferred
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 70 : BindingExpression (hash=2902278): DataContext is null
System.Windows.Data Warning: 66 : BindingExpression (hash=2902278): Resolving source (last chance)
System.Windows.Data Warning: 69 : BindingExpression (hash=2902278): Found data context element: TextBlock (hash=18876224) (OK)
System.Windows.Data Warning: 77 : BindingExpression (hash=2902278): Activate with root item <null>
System.Windows.Data Warning: 105 : BindingExpression (hash=2902278): Item at level 0 is null - no accessor
System.Windows.Data Warning: 79 : BindingExpression (hash=2902278): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 87 : BindingExpression (hash=2902278): TransferValue - using fallback/default value ''
System.Windows.Data Warning: 88 : BindingExpression (hash=2902278): TransferValue - using final value ''
By reading through the list, you can actually see the entire process that WPF goes through to try to find a proper value for your TextBlock control.
Several times you will see it being unable to find a proper DataContext, and in the end, it uses the default {DependencyProperty.UnsetValue} which
translates into an empty string.
Using the real debugger
The above trick can be great for diagnosing a bad binding, but for some cases, it’s easier and more pleasant to work with the real debugger. Bindings
doesn’t natively support this, since they are being handled deep inside of WPF, but using a Converter, like shown in a previous article, you can actually
jump into this process and step through it. You don’t really need a Converter that does anything useful, you just need a way into the binding process, and
a dummy converter will get you there:
<Window x:Class="WpfTutorialSamples.DataBinding.DataBindingDebuggingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfTutorialSamples.DataBinding"
Title="DataBindingDebuggingSample" Name="wnd" Height="100" Width="200">
<Window.Resources>
<self:DebugDummyConverter x:Key="DebugDummyConverter" />
</Window.Resources>
<Grid Margin="10">
<TextBlock Text="{Binding Title, ElementName=wnd, Converter={StaticResource DebugDummyConverter}}" />
</Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
using System.Diagnostics;
namespace WpfTutorialSamples.DataBinding
{
public partial class DataBindingDebuggingSample : Window
{
public DataBindingDebuggingSample()
{
InitializeComponent();
}
}
public class DebugDummyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Debugger.Break();
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Debugger.Break();
return value;
}
}
}
In the Code-behind file, we define a DebugDummyConverter. In the Convert() and ConvertBack() methods, we call Debugger.Break(), which has the same effect
as setting a breakpoint in Visual Studio, and then return the value that was given to us untouched.
In the markup, we add a reference to our converter in the window resources and then we use it in our binding. In a real world application, you should
define the converter in a file of its own and then add the reference to it in App.xaml, so that you may use it all over the application without having to
create a new reference to it in each window, but for this example, the above should do just fine.
If you run the example, you will see that the debugger breaks as soon as WPF tries to fetch the value for the title of the window. You can now inspect the
values given to the Convert() method, or even change them before proceeding, using the standard debugging capabilities of Visual Studio.
If the debugger never breaks, it means that the converter is not used. This usually indicates that you have an invalid binding expression, which can be
diagnosed and fixed using the methods described in the start of this article. The dummy-converter trick is only for testing valid binding expressions.
This article has been fully translated into the following languages:
-
Bulgarian
-
Chinese
-
Danish
-
French
-
German
-
Italian
-
Japanese
-
Polish
-
Portuguese
-
Russian
-
Spanish
-
Swedish
-
Vietnamese
Is your preferred language not on the list? Click here to help us translate this article into your language!
I noticed, that the application output is filled with messages, that a BindingExpression path error occured, when using a ComboBox:
System.Windows.Data Error: 40 : BindingExpression path error: '(adonisExtensions:WatermarkExtension.IsWatermarkVisible)' property not found on 'object' ''ComboBox' (Name='')'. BindingExpression:Path=(adonisExtensions:WatermarkExtension.IsWatermarkVisible); DataItem='ComboBox' (Name=''); target element is 'TextBox' (Name='PART_EditableTextBox'); target property is 'NoTarget' (type 'Object')
Exception thrown: 'MS.Internal.Xaml.Parser.GenericTypeNameParser.TypeNameParserException' in System.Xaml.dll
System.Windows.Data Error: 40 : BindingExpression path error: '(adonisExtensions:WatermarkExtension.Watermark)' property not found on 'object' ''ComboBox' (Name='')'. BindingExpression:Path=(adonisExtensions:WatermarkExtension.Watermark); DataItem='ComboBox' (Name=''); target element is 'ContentPresenter' (Name='PlaceholderHost'); target property is 'Content' (type 'Object')
Exception thrown: 'MS.Internal.Xaml.Parser.GenericTypeNameParser.TypeNameParserException' in System.Xaml.dll
These two errors occur for every ComboBox in my view.
I’m using the latest version of AdonisUI (1.9), I haven’t noticed this with earlier versions but I have not tested it specifically with other versions of AdonisUI.
This is the view, the error occurs, the following code snippet is the ComboBox in the view:
<ComboBox Grid.Column="0" ItemsSource="{Binding InstallerBundles}" SelectedItem="{Binding SelectedInstallerBundle}" HorizontalContentAlignment="Stretch" ScrollViewer.CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" VirtualizingStackPanel.ScrollUnit="Pixel"> <ComboBox.ItemsPanel> <ItemsPanelTemplate > <VirtualizingStackPanel/> </ItemsPanelTemplate> </ComboBox.ItemsPanel> </ComboBox>
The view for an installer bundle consists of only a single TextBox:
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding Name}"/>
There seems to be no error while using the application, I just wanted to check, if the errors can be ignored.