can't render the buttons on the entire display in SLXNA - silverlight

I have a SLXNA game and am trying to display a menu on the SL part. The problem is that the buttons seem to display but not entirely. In a certain part of the screen the buttons just stop to be drawn(i can see tje button till a point where it looks like it gets 'cut off'). What could be the problem?
note: the app is in landscape and is a default SL/XNA template
here is the code(i will only display the code that interests us):
XAML :
</Grid.RowDefinitions>
<!-- Toggles the visibility of the ColorPanel -->
<Button VerticalAlignment="Top" BorderBrush="DarkRed" Foreground="DarkRed" Margin="1,0,-1,0">pause</Button>
<Button VerticalAlignment="Bottom" BorderBrush="DarkRed" Foreground="DarkRed" Margin="1,0,-1,0">change</Button>
<!-- Arrange buttons in a horizontal line by using StackPanel -->
</Grid>
i declare :
UIElementRenderer elementRenderer;
public GamePage()
{
// some typical code.....
LayoutUpdated += new EventHandler(GamePage_LayoutUpdated);
}
void GamePage_LayoutUpdated(object sender, EventArgs e)
{
// Create the UIElementRenderer to draw the XAML page to a texture.
// Check for 0 because when we navigate away the LayoutUpdate event
// is raised but ActualWidth and ActualHeight will be 0 in that case.
if (ActualWidth > 0 && ActualHeight > 0 && elementRenderer == null)
{
elementRenderer = new UIElementRenderer(this, (int)ActualWidth, (int)ActualHeight);
}
}
private void OnDraw(object sender, GameTimerEventArgs e)
{
SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.LightGoldenrodYellow);
// draw some 3d objects
elementRenderer.Render();
spriteBatch.Begin();
spriteBatch.Draw(elementRenderer.Texture, Vector2.Zero, Color.White);
spriteBatch.End();
// TODO: Add your drawing code here
}

I've seen this before. I think the problem here is that because your page is Landscape it actually gets created first by Silverlight as Portrait and then "rotated" around - leaving your UIElementRenderer with the wrong size and everything looking wrong.
Try recreating your UIElementRenderer in response to the OrientationChanged event. (i.e. call the code you have in the GamePage_LayoutUpdated method again)

Related

Custom window drag handler interferes with scrollviewer bar drag

I have a window with window style set to None that handles OnPreviewMouseDown, OnPreviewMouseUp, and OnMouseMove so that the window can be dragged from anywhere.
The windows code behind looks like this:
bool inDrag;
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonDown(e);
inDrag = true;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (inDrag && e.LeftButton == MouseButtonState.Pressed)
{
this.DragMove();
}
}
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonUp(e);
if (inDrag)
{
inDrag = false;
}
}
Now problem is I have a large menu in this window that has a scroll bar which works with the scroll wheel and by clicking to a position on the scrollviewer but not when clicking and dragging the scroll bar itself. Also if I click and hold and move my cursor not on top of the window the scrolling works again. This has led me to believe that the above dragging implementation is blocking the scrollviewers drag functionality.
I tried manually raising the event with .RaiseEvent(e) in OnMouseMove but this causes a stack overflow exception when I move my mouse over the window.
How can I get my Scrollviewer to respond to mouse movements without removing my click and drag window behavior?
<!--ScrollViewer subscribed to PreviewMouseDown to set inDrag to false-->
<ScrollViewer Visibility="Visible" Mouse.PreviewMouseDown="ScrollViewer_PreviewMouseDown">
<!--The Grid fill all the available space and is subscribed to PreviewMouseDown event to set inDrag to true-->
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Mouse.PreviewMouseDown="Grid_PreviewMouseDown" Background="Transparent">
<!--My menu-->
</Grid>
</ScrollViewer>
Note that if there is "blank space" (no Background set including that of the Content),
the PreviewMouseDown event won't be raised despite the subscription.
If needed, to work around that you can set the Background of the Grid to Transparent and the event will be raised even on seemingly blank space.

WPF - Maximizing borderless window by taking in account the user taskbar

I am creating a WPF window with a custom chrome, so I setted ResizeMode="NoResize" and WindowStyle="None" to implement my own chrome. However, there is an issue while maximizing the borderless window: it takes the whole screen.
I found the following trick to fix part of the issue:
http://chiafong6799.wordpress.com/2009/02/05/maximizing-a-borderlessno-caption-window/
This successfully restrain the window size to prevent from covering a taskbar. However, if the user have his taskbar positionned at the left or at the top, this won't work, as the window is at position 0,0.
Is there any way to retrieve more accurately the available area, or to query the user taskbar's position so I can position the maximized window accordingly?
I had a quick play around and it seems that setting the Windows Left and Top properties is ignored when setting WindowState.Maximized with a borderless form.
One workaround would be to ignore the WindowState functions and create your own Maximize/Restore functions
Rough example.
public partial class MainWindow : Window
{
private Rect _restoreLocation;
public MainWindow()
{
InitializeComponent();
}
private void MaximizeWindow()
{
_restoreLocation = new Rect { Width = Width, Height = Height, X = Left, Y = Top };
System.Windows.Forms.Screen currentScreen;
currentScreen = System.Windows.Forms.Screen.FromPoint(System.Windows.Forms.Cursor.Position);
Height = currentScreen.WorkingArea.Height;
Width = currentScreen.WorkingArea.Width;
Left = currentScreen.WorkingArea.X;
Top = currentScreen.WorkingArea.Y;
}
private void Restore()
{
Height = _restoreLocation.Height;
Width = _restoreLocation.Width;
Left = _restoreLocation.X;
Top = _restoreLocation.Y;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MaximizeWindow();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Restore();
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
base.OnMouseMove(e);
}
}
Xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="74.608" Width="171.708" ResizeMode="NoResize" WindowStyle="None">
<Grid>
<Button Content="Max" HorizontalAlignment="Left" Margin="0,29,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
<Button Content="Restore" HorizontalAlignment="Left" Margin="80,29,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2"/>
</Grid>
</Window>
Obviously you will want to clean this code up, but it seems to work wherever the Taskbar is located, However you may need to add some logic to get the correct Left, Top if the users font DPI is larger than 100%
Another way to do this is by handling the WM_GETMINMAXINFO Win32 message. The code here shows how to do that.
Note that there are a few things that I would do differently, such as returning IntPtr.Zero instead of (System.IntPtr)0 in WindowProc and making MONITOR_DEFAULTTONEAREST a constant. But that's just coding style changes, and doesn't affect the net result.
Also make sure to pay attention to the update where the WindowProc is hooked during the SourceInitialized event instead of OnApplyTemplate. That's the better place to do it. If you're implementing a class derived from Window, then another option is to override OnSourceInitialized to hook the WindowProc instead of attaching to the event. That's what I normally do.

Removing a UserControl added at runtime using a button within UserControl

I have seen a few posts addressing how to remove an UserControl that has been added during runtime, but my problem is a little different. I have a UserControl that consists of an image with a small "x" button on the top right corner that is used to remove itself (the UserControl) from its parent canvas. Also to note is that the UserControl is added during runtime when the user doubleclicks on a ListboxItem. I have a Click event handler for the top right corner button but this code is not running at all. I know this because I have a breakpoint in this code which is not reached when I click the button.
So,
Why isn't the click event of the remove button being handled?
Maybe there is a better way to implement this. Please advise.
Here's the code used for adding it:
private void MyListBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.OriginalSource.ToString() == "System.Windows.Controls.Border" || e.OriginalSource.ToString() == "System.Windows.Controls.Image" || e.OriginalSource.ToString() == "System.Windows.Controls.TextBlock")
{
Expression.Blend.SampleData.MyCollection.Dataset lbi = ((sender as ListBox).SelectedItem as Expression.Blend.SampleData.MyCollection.Dataset);
var new_usercontrol = new MyUserControl();
new_usercontrol.MyImageSourceProperty = lbi.Image;
MyCanvas.Children.Add(new_usercontrol);
Canvas.SetLeft(new_usercontrol, 100);
Canvas.SetTop(new_usercontrol, 100);
Canvas.SetZIndex(new_usercontrol, 100);
}
}
The following is the cs code for the UserControl:
public partial class ModuleElement : UserControl
{
public ImageSource MyProperty
{
get { return (ImageSource)this.image.Source; }
set { this.image.Source = value; }
}
public ModuleElement()
{
this.InitializeComponent();
}
private void RemoveButton_Click(object sender, RoutedEventArgs e)
{
((Canvas)this.Parent).Children.Remove(this);
}
}
The XAML:
<Grid x:Name="LayoutRoot">
<Image x:Name="image" />
<Button x:Name="RemoveButton" Content="X" HorizontalAlignment="Right" Height="17.834" Margin="0" VerticalAlignment="Top" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Click="RemoveButton_Click">
</Button>
</Grid>
Thanks in advance,
Bryan
So I tried your code here exactly except for some name changes and could not reproduce your issue. In my personal experience your issue here has to be that for some reason the event for the click isn't subscribed to properly. For this I would go into designer for the user control, wipe out the current event for the button and double click in the designer event textbox such that VS or Blend generates all the code necessary for a proper subscription.
I have created a sample based on your code here. Feel free to pull it down and take a look to see if you can find any inconsistencies.
As far as a better way to implement this, check out the good old MVVM pattern and the MVVM Light Toolkit. With this you can have a central ViewModel class that will handle all of your button commands and binding without code behind.

WPF Popup focus in data grid

I'm creating a custom UserControl to be used inside a DataGrid editing template.
It looks like this:
<UserControl
x:Class="HR.Controls.UserPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:tk="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock x:Name="PART_TextBox" Text="Hello WOrld" />
<Popup Width="234" Height="175" IsOpen="True" StaysOpen="True"
Placement="Bottom"
PlacementTarget="{Binding ElementName=PART_TextBox}"
>
<TextBox
x:Name="searchTextBox"
Text=">Enter Name<"/>
</Popup>
</Grid>
</UserControl>
edit:
I've narrowed down the code a bit.
It seems that if I put a Popup with textbox inside the CellEditingTemplate directly the textbox gets focus no problem. When I move that code into a UserControl I can no longer select the textbox when editing the cell.
Is the UserControl doing something funny with the focus ?
The problem is when i edit the cell in the datagrid I get the user control showing up but I can't click in the TextBox searchTextBox. When I click on it the popup closes and the cell goes back to default.
I have tried copying and pasting all the code inside the user control and pasting it directly into the CellEditingTemplate and that interacts the way it should.
I was just wondering if the UserControl did something weird that prevents a popup from gaining focus because it works as expected when directly placed in the CellEditingTemplate ?
Thanks,
Raul
Not sure if this will help anyone, but this helps if you have custom controls in the datagrid with a popup..... this fixed my problem, and it was one line of xaml. I spend the whole day re-reading this forum and then looking at the source for DataGridCell. Hope this helps.
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Focusable" Value="False"></Setter>
</Style>
I had a similar problem where a Popup embedded in a UserControl as a cell editing template would close when certain areas of it were clicked. The problem turned out to be that the WPF Toolkit (and presumably WPF4) DataGrid is very greedy with left mouse clicks. Even when you handle them and set Handled to true, the grid can interpret them as clicking into a different cell.
This thread has the full details, but the fix is to hook into DataGrid.CellEditEnding event and cancel the end edit:
private static void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.Column.GetType() == typeof(DataGridTemplateColumn))
{
var popup = GetVisualChild<Popup>(e.EditingElement);
if (popup != null && popup.IsOpen)
{
e.Cancel = true;
}
}
}
private static T GetVisualChild<T>(DependencyObject visual)
where T : DependencyObject
{
if (visual == null)
return null;
var count = VisualTreeHelper.GetChildrenCount(visual);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(visual, i);
var childOfTypeT = child as T ?? GetVisualChild<T>(child);
if (childOfTypeT != null)
return childOfTypeT;
}
return null;
}
Full credit for this goes to the Actipro thread.
Set FocusManager.IsFocusScope Attached Property on the Popup to True
I had a kinda simular problem, i created a usercontrol containing a textbox, a button and a calendar. Basicaly i create my own datepicker with custom validation logic.
I put this component in a CellEditingTemplate. When i pressed the button, the popup showed, but clicking the popup anywhere caused the cell te stop editing (because the popup was taking focus from the textbox). I solved it by adding code that sais that if the popup is open, the focus of the textbox may not be lost. This did the trick for me.
Also, the in the on loaded event handler of the usercontrol i give focus to the textbox.
In your case it's propably the Usercontrol itsefl that has focus.
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e) {
// Don't allow focus to leave the textbox if the popup is open
if (Popup.IsOpen) e.Handled = true;
}
private void Root_Loaded(object sender, RoutedEventArgs e) {
TextBox.Focus();
}

Cant drag and move a WPF Form

I design a WPF form with Window Style=None. So I Cannot see the drag bar in the form. How can I move the Form with WindowStyle=None Property?
I am using a main window to hold pages (creating a navigation style program), and in the code behind of my main window, I inserted this...
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// Begin dragging the window
this.DragMove();
}
... and it works like a charm. This is with windowstyle=none. Its nice in the sense that you can click anywhere on the app and move it instead of just being limited to a top bar.
See this question.
Basically you use the Window.DragMove method for this.
In our application we have Windows with WindowStyle set to "none", we implemented the functionality to drag the Window, but only from the header rather than from any point in the Window. We did this by adding a Border as a header, then adding a Thumb to fill the entire Border. We then handle the DragDelta method on the Thumb in the code-behind for the Window.
<Border
Name="headerBorder"
Width="Auto"
Height="50"
VerticalAlignment="Top"
CornerRadius="5,5,0,0"
DockPanel.Dock="Top"
Background="{StaticResource BackgroundBrush}"
BorderThickness="1,1,1,1"
BorderBrush="{StaticResource BorderBrush}">
<Grid>
<Thumb
x:Name="headerThumb"
Opacity="0"
Background="{x:Null}"
Foreground="{x:Null}"
DragDelta="headerThumb_DragDelta"/>
</Grid>
</Border>
Then in the code-behind we have the following event handler...
private void headerThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
Left = Left + e.HorizontalChange;
Top = Top + e.VerticalChange;
}
I don't know if this is any better than the other method, it's just the way we did it.
either inside the windows on load function or inside the grid's on load function use a deligate to trigger the DragMove() method on Mouse Click
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
this.MouseLeftButtonDown += delegate{DragMove();};
}
If you simply add this.DragMove(); and you are using Bing Maps, then you will get some frustrating behavior when trying to pan the map.
Using TabbyCool's answer was a good solution however, you can not drag the window against the top of the screen to maximise it.
My solution was just checking that the position.Y of my click relative to my top bar grid was less than a suitable amount.
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
Point pt = e.GetPosition(topBar);
Debug.WriteLine(pt.Y);
if (pt.Y < topBar.ActualHeight)
{
DragMove();
}
}

Resources