Which cell was clicked in the Grid by coordinates? - wpf

I have a Grid with a lot of cells, some of them are empty.I want to determine on which cell was the mouse, when the MouseDown event happened.How is that possible?

The first thing to remember is that a control with a transparent background doesn't generate events for its transparent regions. Either set a color for the grid you want, or bind it to the background color of the Window the grid is in, or the events will not fire.
This code sample demonstrates a computational method for determining grid element location given a MouseMove event. The ButtonClick event arguments are very similar. The relevant methods from this sample are ColumnComputation and RowComputation, which take the position on the control and the column or row definitions, for a linear analysis. The sample operates on the InnerGrid UI Element.
Form Class:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void InnerGrid_PreviewMouseMove(object sender, MouseEventArgs e)
{
this.XCoordinate.Text = e.GetPosition(InnerGrid).X.ToString();
this.YCoordinate.Text = e.GetPosition(InnerGrid).Y.ToString();
this.ColumnPosition.Text = ColumnComputation(InnerGrid.ColumnDefinitions, e.GetPosition(InnerGrid).X).ToString();
this.RowPosition.Text = RowComputation(InnerGrid.RowDefinitions, e.GetPosition(InnerGrid).Y).ToString();
}
private double ColumnComputation(ColumnDefinitionCollection c, double YPosition)
{
var columnLeft = 0.0; var columnCount = 0;
foreach (ColumnDefinition cd in c)
{
double actWidth = cd.ActualWidth;
if (YPosition >= columnLeft && YPosition < (actWidth + columnLeft)) return columnCount;
columnCount++;
columnLeft += cd.ActualWidth;
}
return (c.Count + 1);
}
private double RowComputation(RowDefinitionCollection r, double XPosition)
{
var rowTop = 0.0; var rowCount = 0;
foreach (RowDefinition rd in r)
{
double actHeight = rd.ActualHeight;
if (XPosition >= rowTop && XPosition < (actHeight + rowTop)) return rowCount;
rowCount++;
rowTop += rd.ActualHeight;
}
return (r.Count + 1);
}
}
XAML Form:
<Window x:Name="window" x:Class="GridHitTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="OuterBorder" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" HorizontalAlignment="Center" >X Coordinate</TextBlock>
<TextBlock Grid.Column="1" HorizontalAlignment="Center" >Y Coordinate</TextBlock>
<TextBlock Grid.Column="2" HorizontalAlignment="Center" >Column</TextBlock>
<TextBlock Grid.Column="3" HorizontalAlignment="Center" >Row</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" Name="XCoordinate">kjahsd</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" Name="YCoordinate">___ahsdjf</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="2" HorizontalAlignment="Center" Name="ColumnPosition">___ahsdjf</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="3" HorizontalAlignment="Center" Name="RowPosition">___ahsdjf</TextBlock>
<Grid Name="InnerGrid" Margin="20,45,20,10" Grid.ColumnSpan="4" Grid.RowSpan="3" Background="{Binding Background, ElementName=window}" PreviewMouseMove="InnerGrid_PreviewMouseMove" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</Grid>
</Window>

Place a button into the empty cells (or buttons in all cells, but style hidden when other items are present and make the cell not empty). Then when the user clicks on the cell, report the cell such as
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var buttonClicked = sender as Button;
var gridRow = (int)buttonClicked.GetValue( MyGrid.RowProperty );
var gridColumn = (int)buttonClicked.GetValue( MyGrid.ColumnProperty );
}

Here is another option that seems much simpler than the suggested correct answer.
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
var element = (UIElement)e.Source;
int row = Grid.GetRow(element);
int column = Grid.GetColumn(element);
}

Related

Creating a four-way grid splitter in WPF

In my WPF app, I have four separate quadrants, each with it's own grid and data. The four grids are separated by GridSplitters. The GridSplitters allow the user to resize each box by selecting either a horizontal or vertical splitter.
I am trying to allow the user to resize the grids by selecting the center point (circled in red).
I expected to have a four-way mouse pointer that could be used to drag up, down, left, and right. But, I only have the option to move windows up and down... or left and right.
What I've tried:
<Grid> <!-- Main Grid that holds A, B, C, and D -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="5"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="gridA" Grid.Column="0" Grid.Row="0"/>
<GridSplitter Grid.Column="0" Grid.Row="1" Height="5" HorizontalAlignment="Stretch"/>
<Grid x:Name="gridC" Grid.Column="2" Grid.Row="0"/>
<GridSplitter Grid.Column="3" Grid.Row="1" Height="5" HorizontalAlignment="Stretch"/>
<Grid x:Name="gridB" Grid.Column="0" Grid.Row="2"/>
<GridSplitter Grid.Column="1" Grid.Row="0" Width="5" HorizontalAlignment="Stretch"/>
<Grid x:Name="gridD" Grid.Column="2" Grid.Row="2"/>
<GridSplitter Grid.Column="1" Grid.Row="2" Width="5" HorizontalAlignment="Stretch"/>
</Grid>
Let me begin by changing your XAML a little bit, since right now we have four distinct GridSplitters, but two is enough:
<Grid Name="SplitGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="5"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="GridA" Grid.Column="0" Grid.Row="0" Background="Red" />
<Grid x:Name="GridC" Grid.Column="2" Grid.Row="0" Background="Orange" />
<Grid x:Name="GridB" Grid.Column="0" Grid.Row="2" Background="Green" />
<Grid x:Name="GridD" Grid.Column="2" Grid.Row="2" Background="Yellow" />
<GridSplitter x:Name="VerticalSplitter"
Grid.Column="1"
Grid.Row="0"
Grid.RowSpan="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Width="5"
Background="Black" />
<GridSplitter x:Name="HorizontalSplitter"
Grid.Column="0"
Grid.Row="1"
Grid.ColumnSpan="3"
Height="5"
HorizontalAlignment="Stretch"
Background="Black" />
</Grid>
What is more important about this markup is that we now have an intersection point between two splitters:
In order to drag two splitters at a time, we need to know when should we. For that purpose, let's define a Boolean flag:
public partial class View : Window
{
private bool _mouseIsDownOnBothSplitters;
}
We need to update the flag whenever the user clicks on either of the splitters (note that Preview events are used - GridSplitter implementation marks Mouse events as Handled):
void UpdateMouseStatusOnSplittersHandler(object sender, MouseButtonEventArgs e)
{
UpdateMouseStatusOnSplitters(e);
}
VerticalSplitter.PreviewMouseLeftButtonDown += UpdateMouseStatusOnSplittersHandler;
HorizontalSplitter.PreviewMouseLeftButtonDown += UpdateMouseStatusOnSplittersHandler;
VerticalSplitter.PreviewMouseLeftButtonUp += UpdateMouseStatusOnSplittersHandler;
HorizontalSplitter.PreviewMouseLeftButtonUp += UpdateMouseStatusOnSplittersHandler;
The UpdateMouseStatusOnSplitters is the core method here. WPF does not provide multiple layer hit testing "out of the box", so we'll have to do a custom one:
private void UpdateMouseStatusOnSplitters(MouseButtonEventArgs e)
{
bool horizontalSplitterWasHit = false;
bool verticalSplitterWasHit = false;
HitTestResultBehavior HitTestAllElements(HitTestResult hitTestResult)
{
return HitTestResultBehavior.Continue;
}
//We determine whether we hit our splitters in a filter function because only it tests the visual tree
//HitTestAllElements apparently only tests the logical tree
HitTestFilterBehavior IgnoreNonGridSplitters(DependencyObject hitObject)
{
if (hitObject == SplitGrid)
{
return HitTestFilterBehavior.Continue;
}
if (hitObject is GridSplitter)
{
if (hitObject == HorizontalSplitter)
{
horizontalSplitterWasHit = true;
return HitTestFilterBehavior.ContinueSkipChildren;
}
if (hitObject == VerticalSplitter)
{
verticalSplitterWasHit = true;
return HitTestFilterBehavior.ContinueSkipChildren;
}
}
return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
}
VisualTreeHelper.HitTest(SplitGrid, IgnoreNonGridSplitters, HitTestAllElements, new PointHitTestParameters(e.GetPosition(SplitGrid)));
_mouseIsDownOnBothSplitters = horizontalSplitterWasHit && verticalSplitterWasHit;
}
Now we can implement the concurrent dragging. This will be done via a handler for DragDelta. However, there are a few caveats:
We only need to implement the handler for the splitter that is on top (in my case that'll be the HorizontalSplitter)
The Change value in DragDeltaEventArgs is bugged, the _lastHorizontalSplitterHorizontalDragChange is a workaround
To actually "drag" the other splitter, we'll have to change the dimensions of our Column/RowDefinitions. In order to avoid weird clipping behavior (the splitter dragging the column/row with it), we'll have to use the size of it in pixels as the the size of it in stars
So, with that out of the way, here's the relevant handler:
private void HorizontalSplitter_DragDelta(object sender, DragDeltaEventArgs e)
{
if (_mouseIsDownOnBothSplitters)
{
var firstColumn = SplitGrid.ColumnDefinitions[0];
var thirdColumn = SplitGrid.ColumnDefinitions[2];
var horizontalOffset = e.HorizontalChange - _lastHorizontalSplitterHorizontalDragChange;
var maximumColumnWidth = firstColumn.ActualWidth + thirdColumn.ActualWidth;
var newProposedFirstColumnWidth = firstColumn.ActualWidth + horizontalOffset;
var newProposedThirdColumnWidth = thirdColumn.ActualWidth - horizontalOffset;
var newActualFirstColumnWidth = newProposedFirstColumnWidth < 0 ? 0 : newProposedFirstColumnWidth;
var newActualThirdColumnWidth = newProposedThirdColumnWidth < 0 ? 0 : newProposedThirdColumnWidth;
firstColumn.Width = new GridLength(newActualFirstColumnWidth, GridUnitType.Star);
thirdColumn.Width = new GridLength(newActualThirdColumnWidth, GridUnitType.Star);
_lastHorizontalSplitterHorizontalDragChange = e.HorizontalChange;
}
}
Now, this is almost a full solution. It, however, suffers from the fact that even if you move your mouse horizontally outside of the grid, the VerticalSplitter still moves with it, which is inconsistent with the default behavior. In order to counteract this, let's add this check to the handler's code:
if (_mouseIsDownOnBothSplitters)
{
var mousePositionRelativeToGrid = Mouse.GetPosition(SplitGrid);
if (mousePositionRelativeToGrid.X > 0 && mousePositionRelativeToGrid.X < SplitGrid.ActualWidth)
{
//The rest of the handler's code
}
}
Finally, we need to reset our _lastHorizontalSplitterHorizontalDragChange to zero when the dragging is over:
HorizontalSplitter.DragCompleted += (o, e) => _lastHorizontalSplitterHorizontalDragChange = 0;
I hope it is not too daring of me to leave the implementation of the cursor's image change to you.

Stop TextBox in ScrollViewer from growing with content

I have a ScrollViewer with HorizontalScrollBarVisibility set to "Auto" that contains a TextBox. The problem is that when a user enters text, the TextBox keeps growing in order to show the entire content. What do I need to change, so that the TextBox only grabs the available width (but is not smaller than a given minimal width)?
The horizontal scroll-bar should only appear if the available horizontal space is not sufficient for the given minimal width.
The TextBox should only grow if there is more horizontal space available.
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*" MinWidth="50"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="test:"/>
<TextBox Grid.Column="1"/>
</Grid>
</ScrollViewer>
The horizontal scrollbar appears even though the MinWidth constrain is fulfilled:
This seems to be a common problem but I haven't found a satisfying solution on the net.
Here is my solution:
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*" MinWidth="100"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="test:"/>
<local:TextBoxDecorator Grid.Column="1">
<TextBox Text="content content content content content content"/>
</local:TextBoxDecorator>
</Grid>
</ScrollViewer>
c#
public class TextBoxDecorator : Decorator {
// properties
public override UIElement Child {
get {
return base.Child;
}
set {
var oldValue = base.Child;
if (oldValue != null) {
var binding = BindingOperations.GetBinding(oldValue, FrameworkElement.WidthProperty);
if ((binding != null) && (binding.Source == this))
BindingOperations.ClearBinding(oldValue, FrameworkElement.WidthProperty);
}
base.Child = value;
if ((value != null) &&
BindingOperations.GetBinding(value, FrameworkElement.WidthProperty) == null)
BindingOperations.SetBinding(
value,
FrameworkElement.WidthProperty,
new Binding() {
Source = this,
Path = new PropertyPath(FrameworkElement.ActualWidthProperty),
Mode = BindingMode.OneWay
});
}
}
// methods
protected override Size MeasureOverride(Size constraint) {
Size result = base.MeasureOverride(constraint);
if (double.IsInfinity(constraint.Width))
result.Width = (Child as FrameworkElement)?.MinWidth ?? 0.0;
return result;
}
}
Let me know if this was helpful or if you have any feedback.

wpf maskedTextBox Databindings

I am using the following MaskedTextBox http://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox in a person project for my own use. This is a simple example because i am trying to use this on a much bigger program but I am using this program to test this control.
STEPS:
1. Create a wpf application
2. Added a Linq to SQL Class called Prescriptions and added a table called info
{ID | Name | Phone}
The markup for the form is listed below:
<Window x:Class="MaskedTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow" Height="300" Width="300"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Label Name="nameLabel" Margin="2" Target="{Binding ElementName=nameTxt}">_Full Name</Label>
<TextBox Name="nameTxt" Grid.Column="1" Margin="2" Text="{Binding Name}"/>
<Label Name="phoneLabel" Margin="2" Grid.Row="1" Grid.Column="0" Target="{Binding ElementName=phoneTxt}">_Phone Numnber</Label>
<xctk:MaskedTextBox Name="phoneTxt" Margin="2" Grid.Row="1" Grid.Column="1" Text="{Binding Phone}" Mask="(000) 000-0000" />
</Grid>
Code Behind File:
public partial class MainWindow : Window
{
private PrescriptionDataContext pdc = new PrescriptionDataContext();
private List<info> users = new List<info>();
private info U = new info { Id = 1, Name = "Matthew Brown", Phone = "5128289081" };
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var q = pdc.getUser();
foreach (info I in q)
{
users.Add(I);
}
// DOES NOT WORK
this.DataContext = users;
// WORKS
// this.DataContext = U;
}
}
When this loads, you will see that the name field has been binded correctly but the phone control shows only the mask not the underlying data from the table. If I explicity create the class and then bind it like i did above it works.
Ideas??

Dynamically generate textbox to match sum

I'm trying to generate Dynamic Text Box
Starting with two textboxes.
if the value is less than the value in the first textbox then generate another textbox dynamically and let the user enter more values.
This has to be done till the sum of the values of all the text boxes from the second to the last one generated becomes equal to the value of first textbox.
Of course other things need to be generated with the textboxes as well like lables etc. and positioned correctly so i thought of using a grid and generate the grid dynamically but above that i'm lost.
Any Help?
Thanks
i used a scrollviewer with the following code
<ScrollViewer Margin="8,8,8,14.417" Grid.Row="4" Grid.ColumnSpan="5" VerticalScrollBarVisibility="Hidden">
<Grid Margin="8" Grid.Row="4" Grid.ColumnSpan="4" x:Name="amtGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="103"/>
<ColumnDefinition Width="Auto" MinWidth="324"/>
<ColumnDefinition Width="Auto" MinWidth="218"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="crdrnextrows" Margin="32.367,8,8,7.423" SelectedIndex="1" />
<ComboBox Background="#FFC6C3C6" Margin="8" x:Name="comboboxCr" GotKeyboardFocus="comboboxCr_GotKeyboardFocus" Grid.Column="1"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="7.973,8,8,8" x:Name="txtBoxam1" Grid.Column="2" LostFocus="txtBoxam1_LostFocus"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="8,8,33.972,8" x:Name="txtBoxamt2" Grid.Column="3" LostFocus="textBox4_LostFocus"/>
</Grid>
</ScrollViewer>
There is another textbox above that with similar code but without the scroll viewer, now what i was thinking was to dynamically create instances of the grid shown in the scrollviewer as many times as need to make them equal.
Is it possible to create new instances of the same grid and add them to the scollviewer dynamically with code?
Thanks
Looking at the additional information that you gave and given the complexity of the object you are wanting to create, a UserControl would probably be the best fit. This code is an example using a DoubleClick to show how to add the UserControl to your ScrollViewer. You will need to expose properties in the UserControl in order to get the information from your TextBoxes otherwise the Code should be simular to my earlier answer.
i.e:
UserControl Xaml
<UserControl x:Class="WpfApplication1.UserControl1"
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"
d:DesignHeight="70" d:DesignWidth="985">
<Grid Margin="8" Grid.Row="4" Grid.ColumnSpan="4" x:Name="amtGrid" Height="40">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="103"/>
<ColumnDefinition Width="Auto" MinWidth="324"/>
<ColumnDefinition Width="Auto" MinWidth="218"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="crdrnextrows" Margin="32.367,8,8,7.423" SelectedIndex="1" />
<ComboBox Background="#FFC6C3C6" Margin="8" x:Name="comboboxCr" GotKeyboardFocus="comboboxCr_GotKeyboardFocus" Grid.Column="1"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="7.973,8,8,8" x:Name="txtBoxam1" Grid.Column="2" LostFocus="txtBoxam1_LostFocus"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="8,8,33.972,8" x:Name="txtBoxamt2" Grid.Column="3" LostFocus="txtBoxamt2_LostFocus"/>
</Grid>
</UserControl>
Window 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="123" Width="1098" xmlns:my="clr-namespace:WpfApplication1" MouseDoubleClick="Window_MouseDoubleClick">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Name="stackPanel1" VerticalAlignment="top" HorizontalAlignment="Left" >
<my:UserControl1 x:Name="userControl11" Width="1077" />
</StackPanel>
</ScrollViewer>
</Window>
Main Window Code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
UserControl1 newUserControl = new UserControl1();
newUserControl.Width = userControl11.Width;
newUserControl.Height = userControl11.Height;
stackPanel1.Children.Add(newUserControl);
}
}
Here is a basic idea, I am using a StackPanel to hold the TextBox's you may want to use a DockPanel to hold your labels and etc and add that to the StackPanel.
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="350" Width="525">
<Grid>
<StackPanel Name="myContainer">
<TextBox Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" KeyDown="textBox1_KeyDown" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" KeyDown="textBox2_KeyDown"/>
</StackPanel>
</Grid>
</Window>
Code
public partial class MainWindow : Window
{
Collection<Control> myControls = new Collection<Control>();
public MainWindow()
{
InitializeComponent();
myControls.Add(textBox2);
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
int temp;
int sum;
sum = 0;
foreach (TextBox tb in myControls)
{
if (int.TryParse(tb.Text, out temp))
{
sum += temp;
}
}
int test = 0;
if (int.TryParse(textBox1.Text, out test))
{
if (sum < test)
{
TextBox newtb = new TextBox();
newtb.Width = ((TextBox)sender).Width;
newtb.Height = ((TextBox)sender).Height;
newtb.Margin = new Thickness(((TextBox)sender).Margin.Left, ((TextBox)sender).Margin.Top , ((TextBox)sender).Margin.Right , ((TextBox)sender).Margin.Bottom);
newtb.HorizontalAlignment = ((TextBox)sender).HorizontalAlignment;
newtb.KeyDown += new KeyEventHandler(textBox2_KeyDown);
myContainer.Children.Add(newtb);
myControls.Add(newtb);
newtb.Focus();
}
else
this.Background = Brushes.LightBlue;
}
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
textBox2.Focus();
}
}
}
Pass the collection to the item. Then in the set add to the collection as necessary.
public class dynamicInts
{
private int dInt;
private ObservableCollection<DynamicInt> dynamicInts
public int DInt
{
get { return dInt; }
set
{
value = dInt;
int sumInt;
foreach (DynamicInt di in dynamicInts) sumInt += di.Dint)
if (sumInt < 2*dynamicInts) dynamicInts.add(newdynamicInts ...

wp7 slider hangs up

I am trying to use a slider control. It's just the simple control. Nothing fancy. But I run into an issue that is confusing me.
If I put the control on a test page (blank with nothing else) and navigate to it immediately after the app launches , I can slide it around perfectly. But if I navigate to another page first and then to the test page. I get a very weird behavior. The slider control moves in steps. It seems as if it hangs up or is losing focus.
I'm using wp7.1 and I've tested in the emulator and on the phone. Both give me the same result. I don't even know where to start solving this, but i definitely need a slider and for it to move smoothly.
Any ideas?
revised to include xaml:
<phone:PhoneApplicationPage
x:Class="WP7ListBoxSelectedItemStyle.TestPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
xmlns:local="clr-namespace:WP7ListBoxSelectedItemStyle"
xmlns:my="clr-namespace:colordata_controls;assembly=colordata_controls"
shell:SystemTray.IsVisible="True" xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="IPO" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Test" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="8,17,16,-17">
<Slider Height="84" HorizontalAlignment="Left" Margin="10,10,0,0" Name="slider1" VerticalAlignment="Top" Width="460" />
</Grid>
</Grid>
here is a link to a video of it in action in the emulator. https://vimeo.com/36428677
so, I still don't know why the slider sticks that way, but in order to keep moving forward I created my own slider. Hopefully this code helps someone else.
xaml:
<UserControl
x:Name="userControl"
x:Class="controls.pSlider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="76" d:DesignHeight="400" Background="Gray" Foreground="White">
<Grid x:Name="LayoutRoot" Background="Transparent" MouseMove="LayoutRoot_MouseMove" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition Height="10"/>
<RowDefinition/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Rectangle x:Name="colorBar" Margin="20,6" Width="10" Fill="{Binding Background, ElementName=userControl}" Grid.Row="1"/>
<Grid x:Name="g_container" Grid.Row="1" Margin="0,1,0,13">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid x:Name="g_thumb" Height="0" VerticalAlignment="Top" Grid.Row="1">
<Canvas Height="0" VerticalAlignment="Top">
<Path Data="M0,0 L1,0 L1.2,0.5 L1,1 L0,1 z" Margin="0" Stretch="Fill" UseLayoutRounding="False" Width="33" RenderTransformOrigin="0.5,0.5" StrokeThickness="0" Fill="{Binding Foreground, ElementName=userControl}" Height="12" d:LayoutOverrides="VerticalAlignment"/>
<Path Data="M0.3,0.5 L0.5,0 L1.5,0 L1.5,1 L0.5,1 z" Margin="0" Stretch="Fill" UseLayoutRounding="False" Width="33" RenderTransformOrigin="0.5,0.5" StrokeThickness="0" Fill="{Binding Foreground, ElementName=userControl}" Height="12" Canvas.Left="43" d:LayoutOverrides="VerticalAlignment"/>
</Canvas>
</Grid>
<Rectangle x:Name="r_lifter" Margin="0" Grid.Row="2" Height="188" StrokeThickness="0"/>
</Grid>
</Grid>
code:
namespace controls {
public partial class pSlider : UserControl {
public event RoutedEventHandler ValueChanged;
public static readonly DependencyProperty MaxProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(pSlider), new PropertyMetadata(100.0));
public double Maximum {
get { return (double)GetValue(MaxProperty); }
set { SetValue(MaxProperty, value); }
}
public static readonly DependencyProperty MinProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(pSlider), new PropertyMetadata(0.0));
public double Minimum {
get { return (double)GetValue(MinProperty); }
set { SetValue(MinProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(pSlider), new PropertyMetadata(50.0));
public double Value {
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public pSlider() {
InitializeComponent();
Loaded += new RoutedEventHandler(pSlider_Loaded);
}
void pSlider_Loaded(object sender, RoutedEventArgs e) {
if (Value > Maximum)
Value = Maximum;
else if (Value < Minimum)
Value = Minimum;
double min = 0;
double max = g_container.ActualHeight;
r_lifter.Height = Value / (Maximum - Minimum) * (max - min);
}
private Point Position;
private void LayoutRoot_MouseMove(object sender, MouseEventArgs e) {
Point newPosition = e.GetPosition((UIElement)sender);
double delta = newPosition.Y - Position.Y;
double temp = r_lifter.Height - delta;
if (temp > g_container.ActualHeight)
r_lifter.Height = g_container.ActualHeight;
else if (temp < 0)
r_lifter.Height = 0;
else
r_lifter.Height = temp;
double min = 0;
double max = g_container.ActualHeight;
Value = r_lifter.Height / (max - min) * (Maximum - Minimum);
Value = Math.Floor(Value);
RoutedEventHandler handler = ValueChanged;
if (handler != null)
handler(this, e);
Position = e.GetPosition((UIElement)sender);
}
private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Position = e.GetPosition((UIElement)sender);
}
}
}

Resources