Say you're developing a custom control and there's a key template part that your code requires. If the user of your control overrides the template such that the part no longer exists then what exception should be thrown? Consider:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var grid = GetTemplateChild("MySpecialGridPart") as Grid;
if (grid == null)
throw new WhatExceptionGoesHere();
}
I figured going with XamlParseException was a good choice but that exception has no public ctor. Is there an appropriate exception type for this or should I just throw new Exception()?
Interestingly most framework controls, including those from Silverlight Toolkit do nothing. See the AutoCompleteTextBox for example, where if components of the control are absent, just does nothing!
I don't think the exact exception type really matters, it is unlikely anyone will catch it explicitly. What is more important is that the string message you supply is informative, detailing the name of the template that is missing.
Related
I'm trying to convert this WPF application to WPF UserControl so I could use it in WinForms application via ElementHost. I'm new to WPF and have never even touched it prior to this attempt so I might be going about it completely the wrong way.
I got the UserControl project to compile, however, my StaticResources get underlined in VS with message "The resource 'x' could not be resolved". I've tried moving the xamls with the needed x:Key elements up one level (the same level as the UserControl Dijagram.xaml), but it still cannot resolve them.
In the WinForms app, when trying to add the UserControl through designer by selecting hosted content in ElementHost tasks I get the following error:
An error occured trying to create an object of type
'DijagramLC.Dijagram'. Make sure the type has a default constructor.
(even though default constructor exists).
However, if I add it in codebehind, like this:
wpfUserControl = new Dijagram();
elementHost1.Child = wpfUserControl;
Controls.Add(elementHost1);
the code compiles but throws this runtime error: "System.Windows.Markup.XamlParseException: 'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '20' and line position '4'. ---> System.Exception: Cannot find resource named 'MyToolbar'. Resource names are case sensitive."
I've tried with and without App.xaml and adding ResourceDictionary elements for problematic xamls, but basically, I have no idea what I'm doing :)
I've uploaded the code to my SkyDrive and would really appreciate it if someone could take a look and tell me what I'm doing wrong:
https://skydrive.live.com/redir.aspx?cid=21be1f8e850e85cc&resid=21BE1F8E850E85CC!353
I hate jumping in blindly to new techonoly like this, but I have had no choice this time, and need to know if my requirement is even achievable this way.
You are probably getting the error because you use resources from a resource dictionary which is not loaded. Loading a resource dictionary in the hosting application will probably solve the issue:
// When hosting a WPF usercontrol inside an element host,
// application resources are not loaded, so we need to load them manually.
var resources = new ResourceDictionary
{
Source = new Uri("/UNIT4.MKB.GUI.XAML.Dashboard.Resources;component/resources.xaml", UriKind.Relative)
};
// Check for null reference
if (Application.Current != null)
{
//Merge the loaded ResourceDictornairy with the dummy application Resources.
Application.Current.Resources.MergedDictionaries.Add(resources);
}
The problem is, you need THE default constructor like this:
public CreatedPollsUC()
{
InitializeComponent();
}
If you have any other code in the constructor, the error occures:
public CreatedPollsUC()
{
InitializeComponent();
// ... more code
}
So if you want to use further code in the constructor, you need to apply the control first to the element host. Then you can edit the constructor.
I'm trying to implement binding validation using Silverlight on Windows Phone, but all I get is the debugger breaking on an unhandled exception instead, and the validation not happening.
I'm following the recommendations from an MSDN article on Data Binding.
Here is what I have tried to do to set it up:
Debug -> Exceptions -> Common Language Runtime Exceptions - User-unhandled is unchecked
On the data template for the ListBoxItem, I declare two-way binding with validations:
<TextBox x:Name="LastReadingValue" Text="{Binding LastReadingValue, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" />
In the setter I raise an exception if the TextBox data is incorrect:
public string LastReadingValue
{
get
{
return _lastReadingValue;
}
set
{
try
{
double reading = System.Convert.ToDouble(value);
_lastReadingValue = String.Format("{0:0.00}", reading);
}
catch (FormatException fe)
{
throw new Exception("The meter reading must be a number like 7561.41");
}
NotifyOfPropertyChanged("LastReadingValue");
}
}
On the ListBox I declare the handler for the BindingValidationError event:
<ListBox x:Name="NewMeterReadingsListBox" ItemsSource="{Binding Meters}" ItemTemplate="{StaticResource NewMeterReadingDataTemplate}" BindingValidationError="ListBox_BindingValidationError"/>
The handler for the BindingValidationError never gets called:
private void ListBox_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
Debug.WriteLine("BindingValidationError");
}
Ok - 2nd try at an answer.
A couple of interesting things happened when I tried this myself. I started from the WindowsPhoneDataboundApplication then added a TextBox and validation to the app's ListBox. I'm using the WP Mango Beta 2 tools (not the Beta 2 update from yesterday).
When debugging: if an invalid value is entered I get a debug break and prompt from VS on the throw line says that the exception is unhandled. HOWEVER: the BindingValidationError handler is called fine, the application keeps running and Application.UnhandledException isn't called.
In the _BindingValidationError function the Debug.WriteLine text is often difficult to spot with the other exception text in the output window. If you make it more obvious by forcing a new line you should spot the text:
Debug.WriteLine("\n\n*** BindingValidationError ***\n");
So basically it's working for me, but there are a couple of things to watch out for when debugging.
If you're targetting WP Mango I'd recommend you consider the Silverlight 4 way of doing data validation which doesn't involve throwing and catching exceptions - I agree with Claus insofar as using exceptions is a really ugly way of doing validation. The SL4 alternative involves implementing the IDataErrorInfo and INotifyDataErrorInfo interfaces in your bound class. I haven't tried this approach personally myself though.
Edit:
If you really want to turn off the break on exceptions you can do it from the VS2010 "Debug" menu, "Exceptions" item. Then de-select the exception type you don't want VS to do break on if it is unhandled.
If you create your own custom Exception class just for binding validation and disable the debug break only for that Exception type, then you will be able to have normal VS behaviour for your app's exceptions except when when dealing with binding failures.
I got my hands om MEF for a week now and I am trying to build up a WPF application that loads imported controls from MEF.
I created a WPF application project and removed the default window and application start up URI. Then I handled the application startup event to compose the application:
public partial class App : Application, IPartImportsSatisfiedNotification
{
{...}
private void App_Startup(object sender, StartupEventArgs e)
{
this.Compose();
}
public void Compose()
{
try
{
globalCatalog.Catalogs.Add(new DirectoryCatalog(extensionsDirectoryPath));
CompositionContainer container = new CompositionContainer(globalCatalog);
container.ComposeParts(this);
}
catch (Exception ex)
{
// Do something
}
}
{...}
}
Actually, when debugging and watching objects after imports are satisfied, everything has hierarchically composed fine like I wanted. But when I try to show up the MainWindow of the application an exception is thrown on MainWindow.Show() call:
"Specified element is already the logical child of another element. Disconnect it first."
Though my code in OnImportsSatisfied method seems fine as it is working when not using MEF mecanism:
public void OnImportsSatisfied()
{
Window mainWindow = new Window();
mainWindow.Content = this.importedControl;
this.MainWindow = mainWindow;
this.MainWindow.Show();
}
I insist on the fact that this works perfectly when not importing controls with MEF. What is surprising is that this code does not work too:
Window mainWindow = new Window();
//mainWindow.Content = this.importedControl;
this.MainWindow = mainWindow;
this.MainWindow.Show();
So I suspect that ComposeParts is doing a bit more than what it says as it is the only member acting on my actual application instance.
Hope someone can help me (Glenn?).
Thanks.
Edit:
I discovered that when I remove the IPartImportsSatisfiedNotification interface from my parts, no exception is thrown and the window shows up. But of course the window is empty as I need this OnImportsSatisfied method to set the DataContext of the window to its associated imported view model.
The sample applications of the WPF Application Framework (WAF) show how to use MEF within a WPF application.
I finally discovered that I was importing my WPF user controls by using the default ImportAttribute constructor, which in fact will make a shared instance of the class if the creation policy is not specified during export. And as many of my controls were implementing the same interface and I was binding them in my views, I was actually trying to add this shared user control instance to different visual elements, which is not permited by WPF (and so the exception).
I marked my imports using the RequiredCreationPolicy set to NonShared and everything got back in order! That was all about learning MEF...
I created this class where I wanted to override this specific event for the content control.
public class MyContentControl : ContentControl
{
protected override void OnKeyUp(KeyEventArgs e)
{
//do something
//..........
e.Handled = true;
}
}
However when I am using this control in my XAML everything compiles and works fine, but I am getting a runtime exception and I am not sure exactly why? Could someone point me in the right directions....
The exception I get is
XamlParseException
UPDATED (Shows where abouts of the exceptions)
In the XAML I have:
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls"
and I use it like:
<ctrls:MyContentControl Grid.Column="0" x:Name="_contentControl" VerticalAlignment="Center" HorizontalAlignment="Center" />
Content controls require a default template to be created somewhere (e.g. in generic.xaml). They do not have a matching XAML file like user controls.
If you can provide more information, I can show you how to create an appropriate template.
There are many reasons for this.
To start with. Give the fully qualified namespace.
Instead of
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls"
Use
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls;assembly=YourAssebmlyName"
If that, doesn't help.
You directly attach your control with the application. Then, enable Debug -> Exceptions. Check Thrown option for the CLR execetion checkbox. You have fair amount of possibility to get to know the cause.
I'm trying to create a UserControl that inherits from a generic class. It does not directly inherit from a generic class, but through an intermediate class that does not use generics. This compiles and works at runtime, but I get an error at design time.
Here's my generic parent class:
Public Class GenericParent(Of T)
Inherits UserControl
End Class
Here's my non-generic parent class:
Public Class NonGenericParent
Inherits GenericParent(Of String)
End Class
Here's my XAML:
<local:NonGenericParent x:Class="SilverlightApplication5.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SilverlightApplication5"
Width="400" Height="300">
<StackPanel>
<Button Content="Hello"/>
</StackPanel>
</local:NonGenericParent>
The IntelliSense parser gives the following errors:
The property 'Width' was not found in type 'NonGenericParent'.
The property 'Height' was not found in type 'NonGenericParent'.
The type 'NonGenericParent' does not support direct content.
It is as though IntelliSense can't see up the inheritance tree past the GenericParent class. I've tried specifying the ContentPropertyAttribute directly on the SilverlightApplication5.Page class, the NonGenericParent class, and it does not work.
I've read that the TypeArguments attribute is not supported in Silverlight 2.0. That is why I've created the intermediate NonGenericParent class.
If anybody has any ideas how to silence these errors I'd be eager to hear them.
Update: We've opened a support ticket with MSFT, I'll update this with whatever their solution is.
We've received word from Microsoft that this is not likely to be fixed in future versions. After they bounced the problem around trying to find the responsible group, it appears that this problem belongs to their WPF developer group, which is where the 'not going to fix it' answer came from.
In the meantime, we've updated our code to yank out the generics from the parent classes until I guess XAML 2009.
Not sure about silverlight, but this compiles and runs as expected in c#:
class GenericObject[T] : UserControl
{
}
class StaticObject : GenericObject[Int32]
{
public Int32 wide { get { return this.Width; } }
}
private void Form1_Load(object sender, EventArgs e)
{
StaticObject so = new StaticObject();
this.Text = so.wide.ToString();
}
So if it compiles against the clr, it should work just fine.
Could be just an intellisense bug as you're suggesting. Normally I'd advise against ignoring comiler warnings, but in this case it seems that the warning is not valid.
edit: substituted angle brackets with square brackets cause SO stripped them.
Despite being at 2.0 silverlight (and especially the VS2008 tweaks for silverlight) are still very young. There are still quirks in the IDE stuff.
Do you still have the problem even after a sucessful build?
This blog post seems to be related to your issue:
http://blogs.msdn.com/b/wpfsldesigner/archive/2010/01/22/known-issue-controls-deriving-from-a-generic-base-class-must-be-in-separate-assembly.aspx
For Silverlight it seems that you must have 3 classes for this to work.