WP8 : Whenever a texbox comes into focus, the corresponding view of the page shifts up by a margin. Due to which the heading of the page gets cut. I have found a solution to this problem here , but it doesn't help. Does not work on WP8. Any solutions are appreciated.
You can disable that shift by changing RenderTransform back to zero:
private void TextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
App.RootFrame.RenderTransform = new TranslateTransform();
}
First you can disable shift using the RenderTransform back to zero as #Ku6opr mentioned. But the real question is would it really do what you want. Noone likes to type if I can not see what I'm typing, this is the reason behind shifting the view upward.
If you really want to prevent shifting redesigning the view for a smaller space will be a much better option. Only disabling the shift somehow wouldn't help much.
Related
I want to write a block diagram design tool (something similar to Simulink or Modelica). I have done something like that already in C++/Qt and C#/WinForms/GDI+, but now I want to go WPF.
Take a block, which can be a rectangle or a square that contains several other smaller shapes as "input/output/bidirectional ports" probably labelled or not, some text and probably a bitmap or vector image. It should provide context menus, basic mouse or drag events (for moving the block, pulling the connections between blocks, etc.) and should allow manual rearrangement of its graphical constituents, maybe in a different editor.
Now imagine a diagram with say 1000 of such blocks (I am exaggerating a bit to allow enough headroom in the future) and corresponding connections. Given that scale, I wonder if I should fall back on to the visual level of WPF and model the interaction part manually or if it is sufficient to use Drawings, Shapes or even Controls for it (like a block being a button).
I am getting a little nervous when I see the ~50 event types a Button supplies and multiply this with the number of blocks times the average number of ports per block. Many elements will just point to the same event handlers or context menus, so these handlers could also be redirected to a management class.
I read through the respective WPF chapters in the book "Pro C# 5.0" and that actually did not allay my fears.
So what level of WPF (visual, drawing, shape, control) is advisable when it comes to speed and memory performance under these requirements?
Sidenote: I am just starting with WPF, so I am a bit stunned about its versatility. It makes strategic decisions a bit difficult for me, which is why I am asking before comprehensively researching.
You could try to create a custom layout with virtualization or use an existing one VirtualizationCanvas.
You need a custom panel for placing your scheme items at correct places in your scheme.
Also, you should create a custom control, based on ItemsControl with custom ItemsControlItems for handling items creating and so on.
Then apply your layout as ItemPanleTemplate for ItemsControl or ListView, where ItemsSource would be bounded to your viewModel with scheme collection.
That's the easiest option, as for me.
So now I have made a small feasibility study on the topic. Add 1800 Buttons to a Canvas, add two mouse events to each of them individually and further add a MouseWheel event to the window to allow basic zooming of the "scene". Observations are on my 10-year old Intel Core2Quad Q6600 + NVidia GTX 460 based machine.
Application starts up fast. Exe is very small (as expected), 8k. Resizing the window (to see more or less of the docked canvas' contents) feels quite snappy. However near fullscreen (all Buttons visible) redraw becomes a little heavy (like ~5Hz refresh rate). App grabs itself 20M of memory instead of 10M with only 1 Button. Zooming is fast enough. Moreover, when zoomed in, the rendering gets noticeably faster (so clipping and such works well). This is good because being in the closely zoomed-in state is the most frequent case when working with larger diagrams. Response to button events is unimpaired in every respect.
Conclusion: using Buttons for diagramming seems doable. It is certainly suboptimal as a graphics app gauged against the capabilities of my machine, but it is still fast enough for the job. Maybe using Shapes instead of Buttons gets a little more out of it. But definitely no case for falling back on low-level graphics.
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="wpf1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wpf1"
Width="513"
Height="385"
x:Name="window1"
MouseWheel="window1_MouseWheel">
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="canvas1" Background="#FFFFE8E8"/>
</Window>
...and...
public partial class Window1 : Window
{
double totalScale = 1;
public Window1()
{
InitializeComponent();
for (int i=0; i<60; i++)
{
for (int j=0; j<30; j++)
{
Button newButton = new Button();
canvas1.Children.Add(newButton);
newButton.Width = 25;
newButton.Height = 25;
Canvas.SetTop(newButton, j*30);
Canvas.SetLeft(newButton, i*30);
newButton.Click += new System.Windows.RoutedEventHandler(button1_Click);
newButton.MouseMove += new System.Windows.Input.MouseEventHandler(button1_MouseMove);
}
}
}
Button lastButton;
void button1_Click(object sender, RoutedEventArgs e)
{
lastButton = sender as Button;
lastButton.Background = Brushes.Blue;
}
void button1_MouseMove(object sender, MouseEventArgs e)
{
Button butt = sender as Button;
if (lastButton != butt) butt.Background = Brushes.Yellow;
}
void window1_MouseWheel(object sender, MouseWheelEventArgs e)
{
double scaleFactor = Math.Pow(1.0005,e.Delta);
totalScale *= scaleFactor;
canvas1.LayoutTransform = new ScaleTransform(totalScale, totalScale);
}
}
I'm not even sure what to call it so let me explain the scenario and hopefully a light bulb goes off for somebody else. I can't do a full code share to reproduce because it just isn't an option, anyhow I digress.
So, here's the basics.
Multiple DataTemplate's set via;
public DataTemplate ABCTemplate
{
get { return (DataTemplate) GetValue(ABCTemplateProperty); }
set { SetValue(ABCTemplateTemplateProperty, value); }
}
Which are swapped out via;
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var something = (thestuff)item;
switch (something.Id)
{
case (int)thestuff.Type.ABC: { return ABCTemplate; }
case (int)thestuff.Type.DEF: { return DEFTemplate; }
case (int)thestuff.Type.GHI: { return GHITemplate; }
case (int)thestuff.Type.JKL: { return JKLTemplate; }
}
return base.SelectTemplate(item, container);
}
etc, etc, etc. Each DataTemplate is a DataGrid (no I did not make this and I can't rewrite it).
Here's the weird mystery part that has me stumped that I'll explain best I can.
On initial load of the screen everything is fine, the data loads fine, everything is peachy. HOWEVER upon Save (even without any changes) once the busy indicator disposes then ONLY the Column Headers of the DataGrids will remain visible UNTIL you resize the screen even the slightest bit. Which I assume causes SizeChanged to UpdateLayout()?
My question is, has anyone seen this behavior before? Why the hell would the DataGrid of each template render the Column Headers, but then NOT render the rows until just a SizeChanged event, and most importantly, how can I fix this P.O.S.?
I tried the first stuff I could think of like just hard setting some sizes since I took a shot in the dark on the fact that changing the window size even the slightest bit causes the data to return to view but in reality, I'm stumped and doing that just made it less predictably reproducible.
I'll happily buy beer for anyone that can save my sanity. Thanks.
This actually does ring a bell. I had to fight a similar DataGrid rendering issue. Here is my story:
The content disappeared or was completely white when we added columns, after a while I found out it happened when the combined width of all columns exceeded a certain number. I don't think it was Int32.MaxValue, it was probably a smaller number, maybe it was a power of two, but that is not important or required. (see my explanation further down)
So your save operation's busy indicator might effect the visualState in any way, some kind of focus border or stuff might be rendered and just hits this magical limit, an overflow will happen.
Now imagine some code that for example calculates the width of a contentPanel or Presenter (or anything related to showing your content) sums up all the parts, and an overflow happens, what will be the result? yeah, exactly, the width will be far in the negative. So it actually might be rendered by the engine, either off screen or just outside of the element's actual display area.
You can actually reproduce this and witness it with a TextBox in a try-out project: Have a TextBox and fill it with random characters via Ctrl+A, Ctrl+C, Ctrl+V, and onTextChanged -> Debug.WriteLine(textbox.Text.GetRenderedWidth()).
(GetRenderedWidth is an extension method I wrote, can give you the code if you want. But it is not super accurate.)
As soon as the rendered width reaches ca. 39,235 you can see a change in the rendering of the Ctrl+A text highlighter: The content is gone! But actually it is just rendered into negative direction (you can turn on EnableRedrawRegions to see it rendered in the wrong direction). and everything is back to normal when you remove the last character again.
So my advise is: turn on EnableRedrawRegions, see if you can see a change of the redrawn regions when your rendering issue occurrs. If you can spot a region is drawn just left of you DataGrid, chances are that that is actually your grid content.
[Edit 1]
If it turns out that the visualState change of the grid is somehow causing this bug, your fix might be as simple as onBusyIndicatorDone -> VisualStateManager.GoToState(grid,"normal",false);
[Edit 2]
You can trigger a redraw with InvalidateArrange or InvalidateMeasure: grid.InvalidateArrange() or grid.InvalidateMeasure()
I have no clue how to ask this question but this is a last ditch effort as I am stumped.
I have this bit of c# code that will send off to a server (using JSON) a request to draw a wms layer to a map. That server goes and does its duty and bam the wms layer appears on the map.
IN this bit of code I sometimes wanna output the times they are clicking on to render this map (its a timeline based render), so using a UserControl in c# that contains a picture box, I render this timeline and then put up a tooltip that shows the various times as the mouse moves along this pictureBox.
The Tooltip is defined as globally:
ToolTip myToolTip;
Then when I use it in my bit of code:
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
//...blah blah blah stuff to calculate time where user clicked based on width of timeline drawn in the picturebox etc.
prisms.callServer("Timetable", "setSelection", selection, null); //call to server to tell it to render the map at the time defined by selection
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
//...blah blah..code to calculate mTheDate showing what the time is where they are where they are hovering
myToolTip.Show(mTheDate, this, toolTipX, toolTipY, 100);
}
So when the scenario above happens, the map doesn't render until i move the mouse off the userControl that has the picturebox on it.
BUT if i take out the myToolTip.show in the MouseMove then minute I click the map renders (i realize it could have lots to do with the WMS server I am hitting etc etc, but it leads me to believe it is something with the tooltips, since removing it makes things work well enough that the map renders without having to move my mouse off the picturebox control).
So I realize this is a vague, hazy question but I am stuck and just throwing this out there for any ideas. Maybe there is something more to the tooltips I don't understand or I need a different approach that does not use the tool tips?
I should also state that the prisms.Call server does get executed (using breakpoint figured this out) even with tool tip there so not sure what is going on.
You could always hide the tooltip (if its showing) while you run the WMS call, then resume showing the tooltip.
I do not have any tooltip-specific knowledge.
After a ton of googling, I couldn't come up with anything..
Is there any way to get a numericUpDown control that does not have the spin box?
I need a textbox that only accepts integers, and a numericUpDown has the perfect behavior that I am looking for. However, I need to hide the numeric spinbox for space constraints.
When I try to do something like numericUpDown.Controls[0].Hide() or numericUpDown.Controls.RemoveAt(0), the spinbox disappears but leaves an unusuable void where the spinbox used to be. Thus the numbers scroll at that point, meaning the space is wasted..
Is there any other solution to this?
Thanks..
You can inherit from NumericUpDown. The trick is to hide control when the control is created.
public class NumericUpDownWitoutButtons : NumericUpDown
{
public NumericUpDownWitoutButtons()
{
Controls[0].Visible = false;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(SystemColors.Window);
base.OnPaint(e);
}
}
If the place were buttons should be looks weird, override OnPaint too.
Also, you probably don't need NumericUpDown. Would it be enough to validate that only digits can by typed in? C# Numbers Only Textbox
I settled for disabling the arrow buttons, as less ugly than trying to hide or remove them.
Immediately after this boilerplate code:
internal MainWin()
{
InitializeComponent();
, add this:
myNumericUpDown.Controls[0].Enabled = false; // Disable the arrow buttons.
Also: set InterceptArrowKeys to false in the control's properties, to prevent arrow keys (on the keyboard) from incrementing and decrementing myNumericUpDown.Value.
Bad ways:
myNumericUpDown.Controls[0].Hide(); // Hide the arrow buttons.
// This leaves a gray patch that turns white after minimize-and-restore.
myNumericUpDown.Controls.RemoveAt(0); // Remove the arrow buttons.
// This leaves a gray patch that turns white after minimize-and-restore.
Half-bad way:
Forget the above. Only set Increment to 0 in the control's properties. The arrow buttons still operate, and the arrow keys (on the keyboard) are still intercepted, but now they do nothing. Sadly, no-action buttons are probably less intuitive than disabled arrow buttons. (I'm surprised that it even accepts Increment = 0. A smart version of this control would neatly hide the arrow buttons when the increment is 0.)
Other solution(s):
A number-box can be implemented as a TextBox with extra code that restricts input to only numbers, and returns or announces a numeric value (decimal or your choice). (Searching finds many diverse, complex examples.) Pasted data comes in differently from keystrokes, so additional code is needed to handle pastes. (Upside: You can make the number-box smarter than the built-in NumericUpDown: NumericUpDown stupidly accepts and displays . until the user presses Enter or leaves the field, even if you specify DecimalPlaces = 0; and it accepts and displays multiple decimal points, which is nonsense.)
An integer-box is simpler than a generalized number-box that accepts real numbers (optionally in floating-point notation) and returns a real-number type (float, double, or decimal).
I want to to make a shared drawing board in C#. This means that two people connected via a TCP connection can draw on this board. The idea (for now) is that people can click on the screen and draw. What do you think is the best method for this?
It's easy enough to draw a dot when the user clicks on a certain spot, but it gets a little more complicated when the user drags the mouse, where you need to draw a line between the last point and the current. Also that doesn't work so well, so I draw a dot where the line starts to improve things a bit, but it's not that good.
Lastly, I need to also send this over TCP, so I need to distinguish between the two. I hoped that I could just send points and have it draw it on the other side, but it seems it wouldn't work. Any ideas except also sending the type?
drawing http://img193.imageshack.us/img193/9697/drawingw.png
EDIT:
ok, I'm going with a IDrawingArgument interface that has Dispatch(myForm), and basically does double dispatch, so it solves the TCP problem (going to serialize/deserialize it).
Lines are still a bit bulky.
One little tip... on your mousemove event. keep a flag that wont fire the event again until the last event that set the flag turns it off. i.e.:
bool isDrawing = false;
public void myCanvas_MouseMove(object sender, EventArgs e)
{
if(!isDrawing)
{
isDrawing = true;
// Do drawing here
isDrawing = false;
}
}
This helped me a lot when doing drawing in a mousemove event.
Dots:
(x,y),(x2,y2),(x3,y3)
Lines:
(x,y,x2,y2),(x3,y3,x4,y4)
Thus, the format is a list of tuples. Tuples of size 4 are lines, of size 2 are points. Note that if your system gets more complicated, you'll really regret not just doing something like:
Dots:
D(x,y),D(x2,y2),D(x3,y3)
Lines:
L(x,y,x2,y2),L(x3,y3,x4,y4)