I just searched for a way to enable a child control while the parent control has IsEnabled = false.
All answers that I have found up to now say that it is not possible - one has to enable the parent and disable the child controls except the ones that should still be enabled.
However, by overriding the Metadata for the IsEnabledProperty in the App.xaml.cs file, I was able to change this default behavior:
protected override void OnStartup(StartupEventArgs e)
{
UIElement.IsEnabledProperty.OverrideMetadata(typeof(FrameworkElement),
new UIPropertyMetadata(true,IsEnabledChanged, CoerceIsEnabled));
}
private void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var childrenCount = VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < childrenCount; ++i)
{
var child = VisualTreeHelper.GetChild(d, i);
child.CoerceValue(UIElement.IsEnabledProperty);
}
}
private object CoerceIsEnabled(DependencyObject d, object basevalue)
{
var parent = VisualTreeHelper.GetParent(d) as FrameworkElement;
if (parent != null && parent.IsEnabled == false)
{
if (d.ReadLocalValue(UIElement.IsEnabledProperty) == DependencyProperty.UnsetValue)
{
return false;
}
}
return basevalue;
}
Now you can manually set the IsEnabled property on a child, which overrides the parent value.
Are there any drawbacks of this approach?
The solution that is proposed in the question may be fine in some scenarios. However, changing the default framework behavior for all UIElements in the application, could introduce compatibility issues and it might be difficult in the future to understand where/why the behavior was changed.
An alternative approach would be to keep the default behavior of the framework and only override that behavior manually in specific places, when needed. One way to do this is be creating a simple wrapper element that breaks the IsEnabled inheritance chain from the parent.
The framework's default coerce callback checks the parent IsEnabled value and inherits it. This control sets a new coerce callback that just returns the value directly without checking inheritance.
public class ResetIsEnabled : ContentControl
{
static ResetIsEnabled()
{
IsEnabledProperty.OverrideMetadata(
typeof(ResetIsEnabled),
new UIPropertyMetadata(
defaultValue: true,
propertyChangedCallback: (_, __) => { },
coerceValueCallback: (_, x) => x));
}
}
It can be used like this
<ParentControl IsEnabled="False">
<!-- Any elements here will have IsEnabled set to false, inherited from the parent -->
<ResetIsEnabled>
<!-- Any child elements here will have IsEnabled set to true (the default value) -->
</ResetIsEnabled>
</ParentControl>
This worked for my situation on a control used several times with some slight modifications.
Placing here to help any future web searchers in a similar situation:
placed it in a static constructor instead of an event, otherwise it tried to set it multiple times and threw a "PropertyMetadata is already registered for type '{type}'." exception.
Changed the type to match the control
Code:
Make sure to find and replace [CustomControl] with the type name of your control.
static [CustomControl]()
{
UIElement.IsEnabledProperty.OverrideMetadata(typeof([CustomControl]), new UIPropertyMetadata(true, [CustomControl]_IsEnabledChanged, CoerceIsEnabled));
}
private static void [CustomControl]_IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var childrenCount = VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < childrenCount; ++i)
{
var child = VisualTreeHelper.GetChild(d, i);
child.CoerceValue(UIElement.IsEnabledProperty);
}
}
private static object CoerceIsEnabled(DependencyObject d, object basevalue)
{
var parent = VisualTreeHelper.GetParent(d) as FrameworkElement;
if (parent != null && parent.IsEnabled == false)
{
if (d.ReadLocalValue(UIElement.IsEnabledProperty) == DependencyProperty.UnsetValue)
{
return false;
}
}
return basevalue;
}
The drawback is at least, that you break the basic concept, and the IsEnabled is not used for the intended scope. This workaround also makes maintenance a bit more complex (the developer has to understand first, why it works differently).
As it is suggested in comments, I would say, that a redesign of this window would help. Especially, if I would like to forbid only the editing (data modification) in the form, I would use other properties like IsReadOnly.
Another option is to override the FrameworkPropertyMetadataOptions to remove the Inherits property. I had a similar problem with the FontSize and this worked well:
FontSizeProperty.OverrideMetadata(
typeof(YourControl),
new FrameworkPropertyMetadata(8.0,
FrameworkPropertyMetadataOptions.None, changed));
Related
The Setting:
I have a RichTextBox containing a hyperink and a DropDownButton somewhere else in my UI. Now when I click the button's DropDown open and afterwards click somewhere else on my UI, the DropDown is implemented to close, and check if it still owns the keyboardfocus so it can set its ToggleButton to focused again after the DropDown collapsed as intended.
The Problem:
When clicking inside my RichTextBox I will face an InvalidOperationException caused by my method to check focus ownership. The call to VisualTreeHelper.GetParent(potentialSubControl) works fine for all elements that are part of the VisualTree. Apparently the focused Hyperlink (returned by FocusManager.GetFocusedElement()) is not part of the VisualTree and therefore is invalid input to GetParent(). Well, how can I find the parent (either logical parent or visual parent) of a hyperlink within my RichTextBox?
My method for determining focus ownership:
// inside DropDownButton.cs
protected override void OnLostFocus( RoutedEventArgs e )
{
base.OnLostFocus( e );
if (CloseOnLostFocus && !DropDown.IsFocused()) CloseDropDown();
}
// inside static class ControlExtensions.cs
public static bool IsFocused( this UIElement control )
{
DependencyObject parent;
for (DependencyObject potentialSubControl =
FocusManager.GetFocusedElement() as DependencyObject;
potentialSubControl != null; potentialSubControl = parent)
{
if (object.ReferenceEquals( potentialSubControl, control )) return true;
try { parent = VisualTreeHelper.GetParent(potentialSubControl); }
catch (InvalidOperationException)
{
// can happen when potentialSubControl is technically
// not part of the visualTree
// for example when FocusManager.GetFocusedElement()
// returned a focused hyperlink (System.Windows.Documents.Hyperlink)
// from within a text area
parent = null;
}
if (parent == null) {
FrameworkElement element = potentialSubControl as FrameworkElement;
if (element != null) parent = element.Parent;
}
}
return false;
}
[Edit]
One potential idea to solve the issue: since Hyperlink is a DependencyObject I could try to access its inheritance context and find other DependencyObjects higher up in the tree and test them for being FrameworkElements. But I struggle to find any information about inheritance context in Silverlight.
I have a TabControl that contains several tabs. Each tab has one UserControl on it. I would like to check the visibility of a control x on UserControl A from UserControl B. I figured that doing x.Visible from UserControl B would be good enough. As it turns out, it was displaying false in the debugger even though I set it explicitly to true and it was never changed. Then I read on MSDN for Control.Visible that:
Even if Visible is set to true, the control might not be visible to the user if it is obscured behind other controls.
So much to my surprise, that will not work. Now I'm wondering how I can tell if the control x is visible from a different UserControl. I would like to avoid using a boolean if possible. Has anyone run into this and found a solution?
Note: It also appears that Control.IsAccessible is false in this situation.
Unfortunately the control doesn't provide anything public that will allow you to check this.
One possibility would be to set something in the controls 'Tag' property. The tag’s purpose is to associate user data with the control. So it can be anything not just a boolean.
Here is the Tag property doc
If you really want the brute force way, you can use Reflection, basically calling GetState(2):
public static bool WouldBeVisible(Control ctl)
{
// Returns true if the control would be visible if container is visible
MethodInfo mi = ctl.GetType().GetMethod("GetState", BindingFlags.Instance | BindingFlags.NonPublic);
if (mi == null) return ctl.Visible;
return (bool)(mi.Invoke(ctl, new object[] { 2 }));
}
Please try this:
bool ControlIsReallyVisible(Control C)
{
if (C.Parent == null) return C.Visible;
else return (C.Visible && ControlIsReallyVisible(C.Parent));
}
I'm using this code not only checking all the ancestors visible and also who is the root control. Checking a root is needed when the control is not added on the Mainform.
public static class StratoControlExtension
{
public static bool TruelyVisible(this Control control, Control expected_root)
{
if (control.Parent == null) { return control == expected_root && control.Visible; }
return control.Parent.TruelyVisible(expected_root) && control.Visible;
}
}
I love PropertyGrid, well, at least the concept behind it - use reflection and attributes to edit your objects without writing much UI code.
My excitement died out pretty quickly though, the default PropertyGrid shipping with WinForms flat-out sucks. Well, it's fine for editing simple objects and such, but that's as far as it goes.
It doesn't display appropriate UITypeEditors for dynamic properties which have type "Object".
As soon as your objects contain collections, you might be able to edit them with so called CollectionEditor. However, it won't fire PropertyValueChanged event. So once you need to add undo functionality, you're screwed.
And I still haven't found an elegant way to add validation for CollectionEditor.
It's also problematic to implement undo if you have multiple objects selected, because in that case PropertyValueChanged event args ChangedItem is null.
I soon found myself writing hacks to address those issues with less than agreeable results.
What would you do?
Is there an elegant solution to at least the first three issues?
Is there an alternative propertygrid? Preferably free & without PInvokes?
A lot of the PropertyGrid's elegance comes from its simplicity. Above all else, it's designed to play nice with Visual Studio, and i'd expect to see it used primarily in custom UITypeEditors and extensions, rather than in application code.
Presumably the objects you are attaching to the PropertyGrid are classes of your own design? I've found that, in order to make good use of the property grid, you have to heavily decorate your classes and members with attributes.
You may find some joy in writing your own subclasses of CollectionEditor (and other types of editors) and attaching them to class members using the [Editor] attribute - if you can attach this attribute to your dynamic properties, you can force the use of a particular editor.
The only way I can think of adding validation to CollectionEditor is to override the CreateCollectionForm() method, returning an instance of your own, custom subclass of CollectionEditor.CollectionForm. There's a chance you will be able to fire the change events from here.
Unfortunately all I can do is nod and agree with the assertion about implementing undo. You might have to resort to 'backing up' the affected objects via cloning or serialization in order to implement undo.
I've seen alternatives to the built-in property grid control, but they exist mainly to offer different visual styles.
If someone is interested - here is a workaround for the PropertyValueChanged problem that simulates a change by invoking the MemberwiseClone function of System.Object if the CollectionEditor's PropertyValueChanged had been fired ...
public class FixedCollectionEditor : CollectionEditor
{
bool modified;
public FixedCollectionEditor(Type type)
: base(type)
{ }
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
{
value = base.EditValue(context, provider, value);
if (value != null && modified)
{
value = value.GetType()
.GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic)
.Invoke(value, new object[] { });
}
modified = false;
return value;
}
protected override CollectionForm CreateCollectionForm()
{
CollectionForm collectionForm = base.CreateCollectionForm();
foreach (Control table in collectionForm.Controls)
{
if (!(table is TableLayoutPanel)) { continue; }
foreach (Control c1 in table.Controls)
{
if (c1 is PropertyGrid)
{
PropertyGrid propertyGrid = (PropertyGrid)c1;
propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(GotModifiedHandler);
}
if (c1 is TableLayoutPanel)
{
foreach (Control c2 in c1.Controls)
{
if (!(c2 is Button)) { continue; }
Button button = (Button)c2;
if (button.Name == "addButton" || button.Name == "removeButton")
{
button.Click += new EventHandler(GotModifiedHandler);
if (button.ContextMenuStrip != null)
{
button.ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(GotModifiedHandler);
}
}
}
}
}
}
return collectionForm;
}
void GotModifiedHandler(object sender, EventArgs e)
{
modified = true;
}
}
Visualhint sells a replacement for the property grid that may help. As I have never used it in a real project, I don't know how well it works.
My goal is to create a reusable Attached Behavior for a FlowDocumentScrollViewer, so that the viewer automaticly scrolls to the end whenever the FlowDocument has been updated (appended).
Problems so far:
OnEnabledChanged gets called before the visual tree is completed, and thus doesn't find the ScrollViewer
I don't know how to attach to the DependencyProperty containing the FlowDocument. My plan was to use it's changed event to initialize the ManagedRange property. (Manually triggered for the first time if needed.)
I don't know how to get to the ScrollViewer property from within the range_Changed method, as it doesn't have the DependencyObject.
I realize that those are potentially 3 separate issues (aka. questions). However they are dependent on each other and the overall design I've attempted for this behavior. I'm asking this as a single question in case I'm going about this the wrong way. If I am, what is the right way?
/// Attached Dependency Properties not shown here:
/// bool Enabled
/// DependencyProperty DocumentProperty
/// TextRange MonitoredRange
/// ScrollViewer ScrollViewer
public static void OnEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d == null || System.ComponentModel.DesignerProperties.GetIsInDesignMode(d))
return;
DependencyProperty documentProperty = null;
ScrollViewer scrollViewer = null;
if (e.NewValue is bool && (bool)e.NewValue)
{
// Using reflection so that this will work with similar types.
FieldInfo documentFieldInfo = d.GetType().GetFields().FirstOrDefault((m) => m.Name == "DocumentProperty");
documentProperty = documentFieldInfo.GetValue(d) as DependencyProperty;
// doesn't work. the visual tree hasn't been built yet
scrollViewer = FindScrollViewer(d);
}
if (documentProperty != d.GetValue(DocumentPropertyProperty) as DependencyProperty)
d.SetValue(DocumentPropertyProperty, documentProperty);
if (scrollViewer != d.GetValue(ScrollViewerProperty) as ScrollViewer)
d.SetValue(ScrollViewerProperty, scrollViewer);
}
private static ScrollViewer FindScrollViewer(DependencyObject obj)
{
do
{
if (VisualTreeHelper.GetChildrenCount(obj) > 0)
obj = VisualTreeHelper.GetChild(obj as Visual, 0);
else
return null;
}
while (!(obj is ScrollViewer));
return obj as ScrollViewer;
}
public static void OnDocumentPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
{
DependencyProperty dp = e.OldValue as DependencyProperty;
// -= OnFlowDocumentChanged
}
if (e.NewValue != null)
{
DependencyProperty dp = e.NewValue as DependencyProperty;
// += OnFlowDocumentChanged
// dp.AddOwner(typeof(AutoScrollBehavior), new PropertyMetadata(OnFlowDocumentChanged));
// System.ArgumentException was unhandled by user code Message='AutoScrollBehavior'
// type must derive from DependencyObject.
}
}
public static void OnFlowDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextRange range = null;
if (e.NewValue != null)
{
FlowDocument doc = e.NewValue as FlowDocument;
if (doc != null)
range = new TextRange(doc.ContentStart, doc.ContentEnd);
}
if (range != d.GetValue(MonitoredRangeProperty) as TextRange)
d.SetValue(MonitoredRangeProperty, range);
}
public static void OnMonitoredRangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
{
TextRange range = e.OldValue as TextRange;
if (range != null)
range.Changed -= new EventHandler(range_Changed);
}
if (e.NewValue != null)
{
TextRange range = e.NewValue as TextRange;
if (range != null)
range.Changed -= new EventHandler(range_Changed);
}
}
static void range_Changed(object sender, EventArgs e)
{
// need ScrollViewer!!
}
OnEnabledChanged gets called before
the visual tree is completed, and thus
doesn't find the ScrollViewer
Use Dispatcher.BeginInvoke to enqueue the rest of the work to happen asynchronously, after the visual tree is built. You will also need to call ApplyTemplate to ensure that the template has been instantiated:
d.Dispatcher.BeginInvoke(new Action(() =>
{
((FrameworkElement)d).ApplyTemplate();
d.SetValue(ScrollViewerProperty, FindScrollViewer(d));
}));
Note that you don't need to check whether the new value is different from the old one. The framework handles that for you when setting dependency properties.
You could also use FrameworkTemplate.FindName to get the ScrollViewer from the FlowDocumentScrollViewer. FlowDocumentScrollViewer has a named template part of type ScrollViewer called PART_ContentHost that is where it will actually host the content. This can be more accurate in case the viewer is re-templated and has more than one ScrollViewer as a child.
var control = d as Control;
if (control != null)
{
control.Dispatcher.BeginInvoke(new Action(() =>
{
control.ApplyTemplate();
control.SetValue(ScrollViewerProperty,
control.Template.FindName("PART_ContentHost", control)
as ScrollViewer);
}));
}
I don't know how to attach to the
DependencyProperty containing the
FlowDocument. My plan was to use it's
changed event to initialize the
ManagedRange property. (Manually
triggered for the first time if
needed.)
There is no way built into the framework to get property changed notification from an arbitrary dependency property. However, you can create your own DependencyProperty and just bind it to the one you want to watch. See Change Notification for Dependency Properties for more information.
Create a dependency property:
private static readonly DependencyProperty InternalDocumentProperty =
DependencyProperty.RegisterAttached(
"InternalDocument",
typeof(FlowDocument),
typeof(YourType),
new PropertyMetadata(OnFlowDocumentChanged));
And replace your reflection code in OnEnabledChanged with simply:
BindingOperations.SetBinding(d, InternalDocumentProperty,
new Binding("Document") { Source = d });
When the Document property of the FlowDocumentScrollViewer changes, the binding will update InternalDocument, and OnFlowDocumentChanged will be called.
I don't know how to get to the
ScrollViewer property from within the
range_Changed method, as it doesn't
have the DependencyObject.
The sender property will be a TextRange, so you could use ((TextRange)sender).Start.Parent to get a DependencyObject and then walk up the visual tree.
An easier method would be to use a lambda expression to capture the d variable in OnMonitoredRangeChanged by doing something like this:
range.Changed += (sender, args) => range_Changed(d);
And then creating an overload of range_Changed that takes in a DependencyObject. That will make it a little harder to remove the handler when you're done, though.
Also, although the answer to Detect FlowDocument Change and Scroll says that TextRange.Changed will work, I didn't see it actually fire when I tested it. If it doesn't work for you and you're willing to use reflection, there is a TextContainer.Changed event that does seem to fire:
var container = doc.GetType().GetProperty("TextContainer",
BindingFlags.Instance | BindingFlags.NonPublic).GetValue(doc, null);
var changedEvent = container.GetType().GetEvent("Changed",
BindingFlags.Instance | BindingFlags.NonPublic);
EventHandler handler = range_Changed;
var typedHandler = Delegate.CreateDelegate(changedEvent.EventHandlerType,
handler.Target, handler.Method);
changedEvent.GetAddMethod(true).Invoke(container, new object[] { typedHandler });
The sender parameter will be the TextContainer, and you can use reflection again to get back to the FlowDocument:
var document = sender.GetType().GetProperty("Parent",
BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(sender, null) as FlowDocument;
var viewer = document.Parent;
Does this help?
It's a good start at least (maybe?).
I am creating sort of a "Navigation panel" (which is actually an ItemControl) for SL and using Regions to allow each module to add his link to the panel.
Problem is that modules loading is inconsistent and thus order of links in the panel can change according to modules loading order.
Restricting the modules order is out of the question.
Other feasible option is the order the region's Views Collection that is binded to the ItemControl, the problem is that ViewCollection is very limited, so ordering it is pretty hard.
Did I miss an option, do you have an idea?
Thanks
Ariel
In Prism4 you just apply the ViewSortHintAttribute to your views:
[ViewSortHint("100")]
class FirstView : UserControl { }
[ViewSortHint("200")]
class SecondView : UserControl { }
The default sort comparer on the regions will pick up this attribute and sort the views accordingly. You can put any string into the attribute but I tend to use medium sized numbers that allow me to easily put a new view in between existing ones.
Refering to Sam's answer you first have to build your comparer. The following one is also capable of views that do not have a dedicated wish to be positioned at. To attach this comparer to the region that has to be sorted you can use a way intruduced by the prism manual:
public partial class MainView : UserControl
{
public MainView( )
{
InitializeComponent( );
ObservableObject<IRegion> observableRegion = RegionManager.GetObservableRegion( ContentHost );
observableRegion.PropertyChanged += ( sender, args ) =>
{
IRegion region = ( (ObservableObject<IRegion>)sender ).Value;
region.SortComparison = CompareViews;
};
}
private static int CompareViews( object x, object y )
{
IPositionView positionX = x as IPositionView;
IPositionView positionY = y as IPositionView;
if ( positionX != null && positionY != null )
{
//Position is a freely choosable integer
return Comparer<int>.Default.Compare( positionX.Position, positionY.Position );
}
else if ( positionX != null )
{
//x is a PositionView, so we favour it here
return -1;
}
else if ( positionY != null )
{
//y is a PositionView, so we favour it here
return 1;
}
else
{
//both are no PositionViews, so we use string comparison here
return String.Compare( x.ToString( ), y.ToString( ) );
}
}
}
At least in prism V4 there you can tell the region manager how to sort the views in a specific region. You just need to provide a compare function to the region.
This example sorts by a very stupid value, the function name:
private static int CompareViews(object x, object y)
{
return String.Compare(x.ToString(), y.ToString());
}
this._regionManager.Regions["MyRegion"].SortComparison = CompareViews;
Of course the region needs to be known to the region manager before you can set the SortComparison. So far the only workaround I found to achieve this was to defer to set the comparison function using the Dispatcher:
private readonly IRegionManager _regionManager;
[ImportingConstructor]
public ShellViewModel(IRegionManager regionManager)
{
this._regionManager = regionManager;
Dispatcher dp = Dispatcher.CurrentDispatcher;
dp.BeginInvoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate
{
if (this._regionManager.Regions.ContainsRegionWithName("MyRegion"))
this._regionManager.Regions["MyRegion"].SortComparison = CompareViews;
}));
}
Of course you should use some more useful information than the class name for the sorting order, but this should be easy to solve.
This is not built into Prism regions, however it's easily implementable.
Damian Schenkelman has posted an extension method he created for adding a region to an index that seems to work pretty well.
http://blogs.southworks.net/dschenkelman/2009/03/14/how-to-add-a-view-to-a-region-in-a-particular-index-with-prism-v2/
Hope this helps.
I found that Sam's solution worked, but discovered that it executes the sort when all views have been added to the region, thus sorting the views twice.
Although it is still a valid solution, reading this post in Prism discussion made me think about a way of implementing this just when the region has been loaded, but before any views have been added yet.
1 - Subscribe to the CollectionChanged of Regions collection
I placed this in the Shell ViewModel code which is the one associated to the View that contains the region I want to sort. Whenever the IRegionManager import has been resolved I subscribe to the CollectionChanged event of its Regions collection:
this._regionManager.Regions.CollectionChanged +=
new NotifyCollectionChangedEventHandler(Regions_CollectionChanged);
2 - Change the SortComparison of the region in the event delegate
Then the delegate Regions_CollectionChanged will execute whenever the Regions collection is updated and will change the SortComparison of my desired region:
void Regions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var o in e.NewItems)
{
IRegion region = o as IRegion;
if (region != null && region.Name == RegionNames.NavigationRegion)
{
region.SortComparison = CompareNavigatorViews;
}
}
}
}
3 - Define the CompareNavigatorViews delegate
In my case, I just sort the views by the title of the assembly where they are contained, you can implement your own compare method here. Remember that the objects you'll receive here are the Views and not the ViewModels.
private static int CompareNavigatorViews(object x, object y)
{
if (x == null)
if (y == null)
return 0;
else
return -1;
else
if (y == null)
return 1;
else
{
AssemblyInfo xAssemblyInfo = new AssemblyInfo(Assembly.GetAssembly(x.GetType()));
AssemblyInfo yAssemblyInfo = new AssemblyInfo(Assembly.GetAssembly(y.GetType()));
return String.Compare(xAssemblyInfo.Title, yAssemblyInfo.Title);
}
}
Just in case somebody asks, the AssemblyInfo class is an utility class I made. To get the title of an assembly you could use this function:
string GetAssemblyTitle(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length == 1)
{
return (attributes[0] as AssemblyTitleAttribute).Title;
}
else
{
// Return the assembly name if there is no title
return this.GetType().Assembly.GetName().Name;
}
}
Hope this helps someone!
Well as the lack of answers counting. I have not found a solution with Prism.
Instead I've used MEF to solve this.
I will write a blog post on it and update this place holder.