Unfortunately, your three requirements does not seem to be achievable using just MinWidth, MaxWidth and WindowState.
But regardless, it's still possible to achieve something similar. What you need to do is to emulate the maximized state of the window. You need to move the window to the correct position, get the right height, and make it unmovable.
The first two parts are easy, the last one requires some more advanced stuff.
Start out with the window you have, with Width, MaxWidth and MinWidth set to 300, and add an event handler to StateChanged.
Width="300" MinWidth="300" MaxWidth="300" StateChanged="MainWindow_OnStateChanged"
And the event handler, and helper methods:
private bool isMaximized;
private Rect normalBounds;
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Maximized && !isMaximized)
{
WindowState = WindowState.Normal;
isMaximized = true;
normalBounds = RestoreBounds;
Height = SystemParameters.WorkArea.Height;
MaxHeight = Height;
MinHeight = Height;
Top = 0;
Left = SystemParameters.WorkArea.Right - Width;
SetMovable(false);
}
else if(WindowState == WindowState.Maximized && isMaximized)
{
WindowState = WindowState.Normal;
isMaximized = false;
MaxHeight = Double.PositiveInfinity;
MinHeight = 0;
Top = normalBounds.Top;
Left = normalBounds.Left;
Width = normalBounds.Width;
Height = normalBounds.Height;
SetMovable(true);
}
}
private void SetMovable(bool enable)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if(enable)
source.RemoveHook(WndProc);
else
source.AddHook(WndProc);
}
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
switch (msg)
{
case WM_SYSCOMMAND:
int command = wParam.ToInt32() & 0xfff0;
if (command == SC_MOVE)
handled = true;
break;
}
return IntPtr.Zero;
}