How to remove the maximize button from Caliburn Windows Manager Dialog - wpf

I am using the Caliburn Micro Window Manager to display a dialog. I would like to remove the maximize and minimize buttons from the dialog.
If I look at the Windows Manager source (under WPF) I can see a third parameter that lets me pass settings to the dialog. My problem is that I can't pass a third parameter - I get an error. This can be replicated in the hello window manager example project.
Any ideas?
Somehow I seem to be referencing an IWindowManager that only allows 2 parameters to ShowDialog.
This is what I want to do but causes an error:
var loginViewModel = new LoginViewModel();
WindowManager windowManager = new WindowManager();
Dictionary<string, object> settings = new Dictionary<string, object>();
// add settings here to pass to dialog
windowManager.ShowDialog(loginViewModel, null, settings);
This is IWindowManager interface that shows 3 parameters:
public interface IWindowManager
{
/// <summary>
/// Shows a modal dialog for the specified model.
/// </summary>
/// <param name="rootModel">The root model.</param>
/// <param name="context">The context.</param>
/// <param name="settings">The optional dialog settings.</param>
/// <returns>The dialog result.</returns>
bool? ShowDialog(object rootModel, object context = null, IDictionary<string, object> settings = null);
/// <summary>
/// Shows a non-modal window for the specified model.
/// </summary>
/// <param name="rootModel">The root model.</param>
/// <param name="context">The context.</param>
/// <param name="settings">The optional window settings.</param>
void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null);
/// <summary>
/// Shows a popup at the current mouse position.
/// </summary>
/// <param name="rootModel">The root model.</param>
/// <param name="context">The view context.</param>
/// <param name="settings">The optional popup settings.</param>
void ShowPopup(object rootModel, object context = null, IDictionary<string, object> settings = null);
}

dynamic settings = new ExpandoObject();
settings.WindowStyle = WindowStyle.ToolWindow;
settings.ShowInTaskbar = false;
settings.Title = "Test";
windowManager.ShowDialog(loginViewModel, "Modeless", settings);

I don't recall any recent version of Caliburn.Micro that used IWindowManager.ShowDialog with three parameters. Are you maybe referring to this link from the Codeplex site? It appears to be a user request that Rob rejected.
As you probably know, ShowDialog() will cause the IWindowManager to instantiate a view it finds (by naming convention) and attach it to whatever viewmodel you provide it (e.g. LoginViewModel is attached to a "found" view called LoginView).
I'm guessing that LoginView is a UserControl for you, but you can have this view be a regular Window and then set the WindowStyle property (in XAML) to use one of the options that does not have the maximize button. This MSDN article shows the various enumeration options. WindowStyle.ToolWindow is the only one that includes the close button and not the min/max buttons, but because it changes the appearance of the close button, you may prefer WindowStyle.None and just define your own window chrome and buttons.
<Window x:Class="MyNamespace.LoginView"
...
WindowStyle="ToolWindow">
...
</Window>

Instead of having your View as Usercontrol make it a Window and set its ResizeMode="NoResize"
<Window x:Class="Company.Project.Views.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ResizeMode="NoResize">
Now you will only have red "X" close button and no maximize/minimize buttons.

Related

Getting the parent window from the most inner WPF usercontrol

I have an WPF User control, let's say UCInner, which contains a WPF Popup. UCInner is used in another WPF user control, let's say UCOuter.
UCOuter is embedded in an ElementHost (ElementHost.Child = UCOuter).
Finally UCOuter is embedded within an Outlook VSTO custom task pane ahd this latter used in a winforms application (Outlook VSTO Add-in).
So from the most inner WPF Control, UCInner, I would like to obtain the parent Window. I have tried some alternatives with no success, I am always getting null or exceptions:
Window w = Window.GetWindow(myPopup);
Window w = Window.GetWindow(UCInner);
I also have tried what explained here and also this one.
UPDATED -
ANOTHER ATTEMPT:
I have tried below piece of code and i can get successfully the window handle, but now from the handle I need to get the Window Object.
dynamic activeWindow = Globals.ThisAddIn.Application.ActiveWindow();
Microsoft.VisualStudio.OLE.Interop.IOleWindow win = activeWindow as Microsoft.VisualStudio.OLE.Interop.IOleWindow;
IntPtr handle;
win.GetWindow(out handle);
So in order to get the Window object I have tried this based on the Window handle:
System.Windows.Interop.HwndSource hwndSource = System.Windows.Interop.HwndSource.FromHwnd(handle);
Window w = hwndSource.RootVisual as Window;
but this does not work, hwndSource is null.
If you need to figure out the right parent window to display your own WPF window, cast Application.ActiveWindow to IOleWindow (Application.ActiveWindow can return either Explorer or Inspector, they both support IOleWindow) and call IOleWindow.GetWindow. Once you have the HWND, create an instance of the WindowInteropHelper class and specify the Outlook window handle as the parent:
if (outlookHwnd != IntPtr.Zero)
{
WindowInteropHelper helper = new WindowInteropHelper(YourDialogWindow);
helper.Owner = outlookHwnd;
YourDialogWindow.ShowInTaskbar = false;
}
First, you need to retrieve the parent window handle, in case of Explorer window in Outlook you can use:
Outlook.Explorer explorer = OutlookApplication.ActiveExplorer();
IOleWindow oleWindow = explorer as IOleWindow;
IntPtr handle = IntPtr.Zero;
oleWindow.GetWindow(out handle);
if (handle != IntPtr.Zero)
{
WindowInteropHelper helper = new WindowInteropHelper(DialogWindow);
helper.Owner = handle;
DialogWindow.ShowInTaskbar = false;
DialogWindow.ShowDialog();
}
where IOleWindow can be defined in the following way:
/// <summary>
/// Implemented and used by containers and objects to obtain window handles
/// and manage context-sensitive help.
/// </summary>
/// <remarks>
/// The IOleWindow interface provides methods that allow an application to obtain
/// the handle to the various windows that participate in in-place activation,
/// and also to enter and exit context-sensitive help mode.
/// </remarks>
[ComImport]
[Guid("00000114-0000-0000-C000-000000000046")]
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleWindow
{
/// <summary>
/// Returns the window handle to one of the windows participating in in-place activation
/// (frame, document, parent, or in-place object window).
/// </summary>
/// <param name="phwnd">Pointer to where to return the window handle.</param>
void GetWindow (out IntPtr phwnd) ;
/// <summary>
/// Determines whether context-sensitive help mode should be entered during an
/// in-place activation session.
/// </summary>
/// <param name="fEnterMode"><c>true</c> if help mode should be entered;
/// <c>false</c> if it should be exited.</param>
void ContextSensitiveHelp ([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode) ;
}

WPF MVVM Dependency Properties

I have the following situation:
I have a User Control with just a single Grid inside.
The Grid has its first column as a checkbox column, which is bound to the IsSelected property of CustomerModel
ItemsSource for the Grid is bound to List< CustomerModel>
When the user checks any of the CheckBoxes the corresponding IsSelected property of CustomerModel is getting updated
Query:
I added a dependency property to the UserControl named "SelectedCustomerItems", and I want it to return a List< CustomerModel> (Only for IsSelected = true)
This UserControl is placed on another Window
The Dependency Property "SelectedCustomerItems" is bound to "SelectedCustomers" property inside the WindowViewModel
But I am not getting the SelectedCustomer Items through this dependency property. Breakpoint is not hitting in Get{} Please suggest....
Implement your DPs this way:
#region SomeProperty
/// <summary>
/// The <see cref="DependencyProperty"/> for <see cref="SomeProperty"/>.
/// </summary>
public static readonly DependencyProperty SomePropertyProperty =
DependencyProperty.Register(
SomePropertyPropertyName,
typeof(object),
typeof(SomeType),
// other types here may be appropriate for your situ
new FrameworkPropertyMetadata(null, OnSomePropertyPropertyChanged));
/// <summary>
/// Called when the value of <see cref="SomePropertyProperty"/> changes on a given instance of <see cref="SomeType"/>.
/// </summary>
/// <param name="d">The instance on which the property changed.</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnSomePropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as SomeType).OnSomePropertyChanged(e.OldValue as object, e.NewValue as object);
}
/// <summary>
/// Called when <see cref="SomeProperty"/> changes.
/// </summary>
/// <param name="oldValue">The old value</param>
/// <param name="newValue">The new value</param>
private void OnSomePropertyChanged(object oldValue, object newValue)
{
}
/// <summary>
/// The name of the <see cref="SomeProperty"/> <see cref="DependencyProperty"/>.
/// </summary>
public const string SomePropertyPropertyName = "SomeProperty";
/// <summary>
///
/// </summary>
public object SomeProperty
{
get { return (object)GetValue(SomePropertyProperty); }
set { SetValue(SomePropertyProperty, value); }
}
#endregion
You must understand that a DependencyProperty isn't just a property with a bunch of junk added, its a hook into the WPF Binding system. This is a vast, complex system that lives below the sea level upon which your DP daintily floats. It behaves in ways that you will not expect, unless you actually learn it.
You are experiencing the first revelation all of us had with DPs: Bindings do NOT access DependencyProperty values via the property accessors (i.e., get and set methods). These property accessors are convenience methods for you to use from code only. You could dispense with them and use DependencyObject.GetValue and DependencyObject.SetValue, which are the actual hooks into the system (see the implementation of the getters/setters in my example above).
If you want to listen for change notification, you should do what I have done above in my example. You can add a change notification listener when registering your DependencyProperty. You can also override the "Metadata" of inherited DependencyProperties (I do this all the time for DataContext) in order to add change notification (some use the DependencyPropertyDescriptor for this, but I've found them to be lacking).
But, whatever you do, do NOT add code to the get and set methods of your DependencyProperties! They won't be executed by binding operations.
For more information about how DependencyProperties work, I highly suggest reading this great overview on MSDN.

Bindable richTextBox still hanging in memory {WPF, Caliburn.Micro}

I use in WFP Caliburn.Micro Framework.
I need bindable richTextbox for Document property. I found many ways how do it bindable richTextBox.
But I have one problem. From parent window I open child window. Child window consist bindable richTextBox user control.
After I close child window and use memory profiler view class with bindabelrichTextBox control and view model class is still hanging in memory. -> this cause memory leaks.
If I use richTextBox from .NET Framework or richTextBox from Extended WPF Toolkit it doesn’t cause this memory leak problem.
I can’t identified problem in bindable richTextBox class.
Here is ist class for bindable richTextBox:
Base class can be from .NET or Extended toolkit.
/// <summary>
/// Represents a bindable rich editing control which operates on System.Windows.Documents.FlowDocument
/// objects.
/// </summary>
public class BindableRichTextBox : RichTextBox
{
/// <summary>
/// Identifies the <see cref="Document"/> dependency property.
/// </summary>
public static readonly DependencyProperty DocumentProperty = DependencyProperty.Register("Document",
typeof(FlowDocument), typeof(BindableRichTextBox));
/// <summary>
/// Initializes a new instance of the <see cref="BindableRichTextBox"/> class.
/// </summary>
public BindableRichTextBox()
: base()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BindableRichTextBox"/> class.
/// </summary>
/// <param title="document">A <see cref="T:System.Windows.Documents.FlowDocument"></see> to be added as the initial contents of the new <see cref="T:System.Windows.Controls.BindableRichTextBox"></see>.</param>
public BindableRichTextBox(FlowDocument document)
: base(document)
{
}
/// <summary>
/// Raises the <see cref="E:System.Windows.FrameworkElement.Initialized"></see> event. This method is invoked whenever <see cref="P:System.Windows.FrameworkElement.IsInitialized"></see> is set to true internally.
/// </summary>
/// <param title="e">The <see cref="T:System.Windows.RoutedEventArgs"></see> that contains the event data.</param>
protected override void OnInitialized(EventArgs e)
{
// Hook up to get notified when DocumentProperty changes.
DependencyPropertyDescriptor descriptor = DependencyPropertyDescriptor.FromProperty(DocumentProperty, typeof(BindableRichTextBox));
descriptor.AddValueChanged(this, delegate
{
// If the underlying value of the dependency property changes,
// update the underlying document, also.
base.Document = (FlowDocument)GetValue(DocumentProperty);
});
// By default, we support updates to the source when focus is lost (or, if the LostFocus
// trigger is specified explicity. We don't support the PropertyChanged trigger right now.
this.LostFocus += new RoutedEventHandler(BindableRichTextBox_LostFocus);
base.OnInitialized(e);
}
/// <summary>
/// Handles the LostFocus event of the BindableRichTextBox control.
/// </summary>
/// <param title="sender">The source of the event.</param>
/// <param title="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
void BindableRichTextBox_LostFocus(object sender, RoutedEventArgs e)
{
// If we have a binding that is set for LostFocus or Default (which we are specifying as default)
// then update the source.
Binding binding = BindingOperations.GetBinding(this, DocumentProperty);
if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default ||
binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus)
{
BindingOperations.GetBindingExpression(this, DocumentProperty).UpdateSource();
}
}
/// <summary>
/// Gets or sets the <see cref="T:System.Windows.Documents.FlowDocument"></see> that represents the contents of the <see cref="T:System.Windows.Controls.BindableRichTextBox"></see>.
/// </summary>
/// <value></value>
/// <returns>A <see cref="T:System.Windows.Documents.FlowDocument"></see> object that represents the contents of the <see cref="T:System.Windows.Controls.BindableRichTextBox"></see>.By default, this property is set to an empty <see cref="T:System.Windows.Documents.FlowDocument"></see>. Specifically, the empty <see cref="T:System.Windows.Documents.FlowDocument"></see> contains a single <see cref="T:System.Windows.Documents.Paragraph"></see>, which contains a single <see cref="T:System.Windows.Documents.Run"></see> which contains no text.</returns>
/// <exception cref="T:System.ArgumentException">Raised if an attempt is made to set this property to a <see cref="T:System.Windows.Documents.FlowDocument"></see> that represents the contents of another <see cref="T:System.Windows.Controls.RichTextBox"></see>.</exception>
/// <exception cref="T:System.ArgumentNullException">Raised if an attempt is made to set this property to null.</exception>
/// <exception cref="T:System.InvalidOperationException">Raised if this property is set while a change block has been activated.</exception>
public new FlowDocument Document
{
get { return (FlowDocument)GetValue(DocumentProperty); }
set { SetValue(DocumentProperty, value); }
}
}
Thank fro help and advice.
Qucik example:
Child window with .NET richTextBox
<Window x:Class="WpfApplication2.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<RichTextBox Background="Green"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
FontSize="13"
Margin="4,4,4,4"
Grid.Row="0"/>
</Grid>
</Window>
This window I open from parent window:
var w = new Window1();
w.Show();
Then close this window, check with memory profiler and it memory doesn’t exist any object of window1 - richTextBox. It’s Ok.
But then I try bindable richTextBox:
Child window 2:
<Window x:Class="WpfApplication2.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:WpfApplication2.Controls"
Title="Window2" Height="300" Width="300">
<Grid>
<Controls:BindableRichTextBox Background="Red"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
FontSize="13"
Margin="4,4,4,4"
Grid.Row="0" />
</Grid>
</Window>
Open child window 2, close this child window and in memory are still alive object of this child window also bindable richTextBox object.
I suspect that since instances of DependencyPropertyDescriptor are likely to be cached at application level, the references to ValueChanged delegate (the anonymous delegate in OnInitialized method) might leak instances of the BindableRichTextBox.
In the code shown there isn't, indeed, any call to DependencyPropertyDescriptor.RemoveValueChanged to remove the handler.
You might consider using the DependencyProperty.Register overload, which supports a PropertyMetadata parameter; this allows you to specify a proper PropertyChangedCallback for the property (see http://msdn.microsoft.com/en-us/library/cc903933(v=VS.95).aspx#metadata):
public static readonly DependencyProperty DocumentProperty =
DependencyProperty.Register("Document",
typeof(FlowDocument), typeof(BindableRichTextBox),
new PropertyMetadata(null,
new PropertyChangedCallback(OnDocumentChanged)
)
);
public static void OnDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((BindableRichTextBox)d).SetBaseDocument((FlowDocument)e.NewValue);
}
public new FlowDocument Document
{
get { return (FlowDocument)GetValue(DocumentProperty); }
set { SetValue(DocumentProperty, value); }
}
private SetBaseDocument(FlowDocument document) {
base.Document = (FlowDocument)GetValue(DocumentProperty);
}
Maybe is better to create user control with richTextBox.
Richtextbox wpf binding

User-friendly way to display a Visual in a WPF application?

Looking for a simple, elegant way to display any given Visual to the user. The only way I can think of off my head is to slap it in a brush and paint it on a Rectangle that's in a ScrollViewer. Not exactly the best option.
You could create a wrapper that inherits from FrameworkElement that would either host your Visual or a generic wrapper that will host any object deriving from Visual.
Take a look at the example in Visual.AddVisual or, if you want to host more than one visual, take a look at the (partial) example in Using DrawingVisual Objects
I don't see a way how you could do that since a Visual has neither a position nor a size. Perhaps stick to FrameworkElement and create a style for it?
My (current) answer is to slap it in an XpsDocument and display it in a DocumentViewer. I could, I suppose, do it a little less complex, but I already have the infrastructure to do it this way. Its not 100%, but it works.
First, a behavior so that I can bind to DocumentViewer.Document (its a friggen POCO, urgh):
public sealed class XpsDocumentBinding
{
#region Document
/// <summary>
/// The <see cref="DependencyProperty"/> for <see cref="Document"/>.
/// </summary>
public static readonly DependencyProperty DocumentProperty =
DependencyProperty.RegisterAttached(
"Document",
typeof(XpsDocument), //
typeof(XpsDocumentBinding),
new UIPropertyMetadata(null, OnDocumentChanged));
/// <summary>
/// Gets the value of the <see cref="DocumentProperty">Document attached property</see> on the given <paramref name="target"/>.
/// </summary>
/// <param name="target">The <see cref="DependencyObject">target</see> on which the property is set.</param>
public static XpsDocument GetDocument(DependencyObject target)
{
return (XpsDocument)target.GetValue(DocumentProperty);
}
/// <summary>
/// Sets the <paramref name="value"/> of the <see cref="DocumentProperty">Document attached property</see> on the given <paramref name="target"/>.
/// </summary>
/// <param name="dependencyObject">The <see cref="DependencyObject">target</see> on which the property is to be set.</param>
/// <param name="value">The value to set.</param>
public static void SetDocument(DependencyObject target, XpsDocument value)
{
target.SetValue(DocumentProperty, value);
}
/// <summary>
/// Called when Document changes.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnDocumentChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var viewer = sender as DocumentViewer;
if (viewer == null)
throw new InvalidOperationException(
"This behavior is only valid on DocumetViewers.");
var doc = e.NewValue as XpsDocument;
if (doc == null)
return;
viewer.Document = doc.GetFixedDocumentSequence();
}
#endregion
}
Then in my model I expose my visual as an XpsDocument
var pack = PackageStore.GetPackage(_uri);
if (pack != null)
return new XpsDocument(pack, CompressionOption.SuperFast, _uri.AbsoluteUri);
MemoryStream ms = new MemoryStream(2048);
Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
PackageStore.AddPackage(_uri, p);
XpsDocument doc = new XpsDocument(p, CompressionOption.SuperFast, _uri.AbsoluteUri);
var writer = XpsDocument.CreateXpsDocumentWriter(doc);
var collator = writer.CreateVisualsCollator();
// write the visuals using our collator
collator.BeginBatchWrite();
collator.Write(Visual);
collator.EndBatchWrite();
p.Flush();
return doc;
Just add a DocumentViewer, bind the result of the conversion method to it via the behavior, and there it is. I'm sure there's a shortcut in here somewhere...

WindowsFormsHost and DependencyProperty

I've got a Windows Forms control that I'm attempting to wrap as a WPF control using the WindowsFormsHost class; I would like to bind the legacy control to a view-model. Specifically, the control exposes a grid property, GridVisible, that I would like to bind a view-model to. I'm using a private, static backing field and a static, read-only property to represent the dependency property (functionally the same as a static, public field, but less mess). When I attempt to set the control's GridVisible property via XAML, it's not updating. Ideas? What am I doing incorrectly?
DrawingHost Class
/// <summary>
/// Provides encapsulation of a drawing control.
/// </summary>
public class DrawingHost : WindowsFormsHost
{
#region Data Members
/// <summary>
/// Holds the disposal flag.
/// </summary>
private bool disposed;
/// <summary>
/// Holds the grid visible property.
/// </summary>
private static readonly DependencyProperty gridVisibleProperty =
DependencyProperty.Register("GridVisible", typeof(bool),
typeof(DrawingHost), new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
/// <summary>
/// Holds the pad.
/// </summary>
private readonly DrawingPad pad = new DrawingPad();
#endregion
#region Properties
/// <summary>
/// Get or set whether the grid is visible.
/// </summary>
public bool GridVisible
{
get { return (bool)GetValue(GridVisibleProperty); }
set { SetValue(GridVisibleProperty, pad.GridVisible = value); }
}
/// <summary>
/// Get the grid visible property.
/// </summary>
public static DependencyProperty GridVisibleProperty
{
get { return gridVisibleProperty; }
}
#endregion
/// <summary>
/// Default-construct a drawing host.
/// </summary>
public DrawingHost()
{
this.Child = this.pad;
}
/// <summary>
/// Dispose of the drawing host.
/// </summary>
/// <param name="disposing">The disposal invocation flag.</param>
protected override void Dispose(bool disposing)
{
if (disposing && !disposed)
{
if (pad != null)
{
pad.Dispose();
}
disposed = true;
}
base.Dispose(disposing);
}
}
XAML
<UserControl x:Class="Drawing.DrawingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:Drawing">
<local:DrawingHost GridVisible="True"/></UserControl>
One of the first rules of dependency properties is to never include any logic in the get and set except the GetValue and SetValue calls. This is because when they are used in XAML, they do not actually go through the get and set accessors. They are inlined with the GetValue and SetValue calls. So none of your code will be executed.
The appropriate way to do this is set up a call-back using the PropertyMetadata parameter in the DependencyProperty.Register method. Then in the call-back you can then execute any extra code.

Resources