I have a Customer Pages which contains information of customer name. This page contains a StackPanel and inside this StackPanel there is a ScrollViewer and inside the ScrollViewer there is another StackPanel.
I am adding number of StackPanels dynamically. Inside the StackPanel I am adding TextBlock dynamically behind, which contains text. Then add InkPresenter to show a separation.
My problem is after adding every time when I try to use the page, it doesn't scroll. In fact if I swipe up the page goes down and come back.
XAML :
<StackPanel>
<ScrollViewer Margin="0,-20,0,0" Grid.RowSpan="2" >
<StackPanel Height="Auto" x:Name="pottilelist" >
</StackPanel>
</ScrollViewer>
</StackPanel>
StackPanel stk = new StackPanel();
stk.Name = g.id.ToString();
stk.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(Customer_Click);
TextBlock tbx = new TextBlock();
tbx.Text = g.customername;
tbx.Name = "A" + g.id.ToString();
tbx.FontSize = 36;
tbx.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(Customer_Click);
tbx.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
stk.Children.Add(tbx);
InkPresenter ink = new InkPresenter();
ink.Height = 4;
ink.Background = Brush3;
ink.Margin = new Thickness(0, 0, 0, 20);
stk.Children.Add(ink);
pottilelist.Children.Add(stk);
In one app it worked, but in another it doesn't.
Try to put the scrol viewer around the Layout Grid (main grid) that contains all page contents. I think this should solve the problem.
As long as you are using Pivot Template , just put it after the deceleration of that pivot item around the grid and it should works !
<phone:PivotItem Header="PivotItem">
<ScrollViewer>
<Grid x:Name="LayoutRoot" Background="#7F000000" >
It depends on where your stackpanel is placed inside the grid.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="1">
<ScrollViewer>
<StackPanel></StackPanel>
</ScrollViewer>
</StackPanel>
</Grid>
In above code scrollviewer will work as expected, because of the height.
If you have set the height of the position in its visual tree, then scrollviewer might not scroll.
I have solved the problem. This problem occurs when there is no height for a stackpanel or scrollviewer. Height Issue
Related
I am a newbie in WPF trying to create his first normal project which is a notes application.
Every note is linked to a button and I thought it'll look beautiful in StackPanel.
I am dynamically creating buttons within StackPanel, but the problem is that when I scroll down the list of Buttons last Button can't be seen fully. I thought it was because of the Margin and tried to adjust it, but it didn't help, also auto Height and Width didn't help. StackPanel is within ScrollViewer and when I reach the end of ScrollBar I just can see half of last button ?
Here is StackPanel's XAML code:
<ScrollViewer VerticalScrollBarVisibility="Auto"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Grid.RowSpan="3" Margin="50 -50 50 5" >
<StackPanel x:Name="ButtonPanel"/>
</ScrollViewer>
That is how I create Button:
dynamicTextBox.Add(SearchNotes);
dynamicTextBox[index_of_buttons] = new TextBox();
Grid.SetRow(dynamicTextBox[index_of_buttons], 1);
Grid.SetColumn(dynamicTextBox[index_of_buttons], 0);
this.ButtonPanel.Children.Add(dynamicTextBox[index_of_buttons]);
dynamicTextBox[index_of_buttons].IsReadOnly = false;
dynamicTextBox[index_of_buttons].Text = "";
Where dynamicTextBox is List<> of TextBoxes to which is applied Template(I think it is not necessary to see Template to resolve the problem)
This is how it looks like:
Can't see the whole button(the last one)
So I wanna see the whole button.
As Andy wrote in the comment section, ListBox is best solution for this problem.
I tried this one to make it look like exactly same as it was in StackPanel
Xaml:
<ListBox Name="ListBoxOfButtons" Background="#404040" BorderThickness="0"
HorizontalContentAlignment="Stretch" Grid.Row="1" Grid.Column="0"
Grid.ColumnSpan="3" Grid.RowSpan="3" Margin="50 -20 50 5">
</ListBox>
C#:
var txtBox = new TextBox();
txtBox.Template = FindResource("TemplateForTextBox") as ControlTemplate;
ListBoxOfButtons.Items.Add(txtBox);
This is how last button looks like now
My goal is to attach a new image control while the application is running.
img = new System.Windows.Controls.Image();
img.Margin = new Thickness(200, 10, 0, 0);
img.Width = 32;
img.Height = 32;
img.Source = etc;
I've tried
this.AddChild(img);// says must be a single element
this.AddLogicalChild(img);// does nothing
this.AddVisualChild(img);// does nothing
It was never this difficult to add a element with forms.
How can I simply attach this new element to the main window (not another control) so that it will show up.
Solved it, I named the grid main, and from there I was able to access the children attribute and the add function
main.children.add(img);
<Window x:Class="Crysis_Menu.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" Loaded="Window_Loaded" AllowsTransparency="False" Background="White" Foreground="{x:Null}" WindowStyle="SingleBorderWindow">
<Grid Name="main">
<Button Content="Run" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="btnRun" VerticalAlignment="Top" Width="151" Click="btnRun_Click" />
<TextBox Height="259" HorizontalAlignment="Left" Margin="12,40,0,0" Name="tbStatus" VerticalAlignment="Top" Width="151" />
</Grid>
</Window>
You should have only one root element under window. Adding the image using this.AddChilda adds the image as child of window, but you probably have some other child defined(Grid for example). Give a name to this child (Grid in the example) and then in the code behind add the image to the Grid
Example :
<Window>
<Grid x:Name="RootGrid">
</Grid>
</Window>
Then in the code behind use
RootGrid.Children.Add(img);
What is this in your case? You can try this.Content = image; or this.Children.Add(image);
If your this is indeed a Window, you should know that Window can have only a single child, which you put into Content. If you want several items in Window, usually you put some appropriate container (for example, Grid or StackPanel) as Window's content, and add children to it.
Vlad got the solution. I used it :
var grid = this.Content as Grid;
// or any controls
Label lblMessage = new Label
{
Content = "I am a label",
Margin = new Thickness(86, 269, 0, 0)
};
grid.Children.Add(lblMessage);
I have created the following piece of code that gets executed when I press an existing button made with the editor
var test = new TextBlock();
test.Text = "meep!";
test.Margin = new Thickness(50, 50, 100, 100);
FrontPage.Children.Add(test);
the code itself is working but after the "meep!" has been added to the screen all buttons created by the editor stop working, how do I fix this?
I guess you are putting the Button element inside a Grid named FrontPage as follows, and invoke the above code snippet in button click event handle. Then after you clicking the button, the TextBlock will be added to the application view but the button cannot be clicked again.
<Grid x:Name="FrontPage" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button
x:Name="btnaddtext"
Margin="117,289,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="btnaddtext_Click"
Content="Button" />
</Grid>
The reason is that if you didn't set the size for the TextBlock, it will stretch to fill the Grid, so that the TextBlock will cover the Button element that inside the Grid and it will not be clickable. TextBlock may be glassy so that you can still see the Button but cannot access. If you change TextBlock to TextBox and update the background color you may see the effects.
You have many ways to resolve this, for example, set Height and Width for the TextBlock as follows:
var test = new TextBlock();
test.Text = "meep!";
test.Height = 100;
test.Width = 100;
test.Margin = new Thickness(50, 50, 100, 100);
FrontPage.Children.Add(test);
Or change a parent layout panel, for example, to a StackPanel.
<StackPanel x:Name="FrontPage" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button
x:Name="btnaddtext"
Margin="117,289,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="btnaddtext_Click"
Content="Button" />
</StackPanel>
There're also other ways. To use which way depends on your requirements and the layout. More details about layout panel please reference layout panels.
I think you foget to add the TextBlock's algment.
You can try add the property to TextBlock and the code is below.
var test = new TextBlock()
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
test.Text = "meep!";
test.Margin = new Thickness(50, 50, 100, 100);
FrontPage.Children.Add(test);
But I think I cant care all what you mean and my code can work.
And you should know that TextBlock cant be edit. The TextBlock only can show the text.
Consider the following XAML:
<Window x:Class="WpfApplication4.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>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="100" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox>
<ListBox.Items>
<ListBoxItem>a</ListBoxItem>
<!-- Another 11 items -->
</ListBox.Items>
</ListBox>
<ListBox Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Items>
<ListBoxItem>1</ListBoxItem>
<!-- Another 23 items -->
</ListBox.Items>
</ListBox>
</Grid>
</Window>
The ListBox in the second row shows the vertical scrollbar as disabled and simply cuts off the content.
I want it to be constrained to the visible area of the window. How to achieve this?
Rational behind setting the height of the second grid row to Auto:
I want the second ListBox to display all its content without a scrollbar if there is enough space for it and the first ListBox should take the remaining space.
I don't think there's any way to do what you want in pure XAML - you have to set a specific height for one or other of the two listboxes, or set fixed proportions for them.
I think you could do what you want with a bit of code in the code behind. Give your RowDefinitions and Listboxes names, as follows, and subscribe to the GridSizedChanged event:
<Grid SizeChanged="GridSizeChanged">
<Grid.RowDefinitions>
<RowDefinition x:Name="row1"/>
<RowDefinition x:Name="row2"/>
</Grid.RowDefinitions>
<ListBox x:Name="lb1">
<ListBox.Items>
<ListBoxItem>a</ListBoxItem>
</ListBox.Items>
</ListBox>
<ListBox x:Name="lb2" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Items>
<ListBoxItem>1</ListBoxItem>
<!-- Another 23 items -->
</ListBox.Items>
</ListBox>
</Grid>
Then handle the event in the following way:
private void GridSizeChanged(object sender, SizeChangedEventArgs e)
{
double newHeight = e.NewSize.Height;
int lb1ItemCount = lb1.Items.Count;
int lb2ItemCount = lb2.Items.Count;
row1.Height = new GridLength(newHeight * lb1ItemCount / (lb1ItemCount + lb2ItemCount));
row2.Height = new GridLength(newHeight * lb2ItemCount / (lb1ItemCount + lb2ItemCount));
}
This sets the size of the two listboxes to be proportional to the number of items they have inside them. If you want to set a minimum size of 100 for the first listbox, you'll have to do a bit more work to set that size first, then base the second size off the calculated value for the first size.
Edit:
I think I've written a version of GridSizeChanged that does exactly what you require. This version will set the height of lb2 to either the whole grid except the top 100px (if the desired listbox size is bigger than this), or just to its own desired size if that is smaller. The first listbox will then fill all remaining space, and will have a minimum height of 100px as you require, because we did not allow lb2 to fill the top 100px.
private void GridSizeChanged(object sender, SizeChangedEventArgs e)
{
lb2.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
double lb2DesiredHeight = lb2.DesiredSize.Height;
double newHeight = e.NewSize.Height;
double lb2AvailableHeight = newHeight - 100;
double lb2ActualHeight = Math.Min(lb2DesiredHeight, lb2AvailableHeight);
row1.Height = new GridLength(newHeight - lb2ActualHeight);
row2.Height = new GridLength(lb2ActualHeight);
}
Hi at present I am using a grid with Image and two Buttons for showing a custom message box in my WP7 application whose visibility is collapsed at first. All is working fine but I have to disable all the controls behind on the page when its visibility is visible. So its quite a overhead to enable/disable lots of control behind.
Is there a better solution for my requirement which are :(1) To show a message box having image and two button or textbox and (2) It should appear in the middle of page.
Thanks in advance!!
You can use built in Popup control with an attached behaviour written by Kent Boogaart, so it would behave like WPF Popup control with PlacementTarget and Placement:
<Popup b:PopupPlacement.PlacementTarget="{Binding ElementName=someElement}">
<b:Popup.PreferredOrientations>
<b:PopupOrientationCollection>
<b:PopupOrientation Placement="Top" HorizontalAlignment="Center"/>
<b:PopupOrientation Placement="Bottom" HorizontalAlignment="Center"/>
<b:PopupOrientation Placement="Right" VerticalAlignment="Center"/>
<b:PopupOrientation Placement="Right" VerticalAlignment="TopCenter"/>
</b:PopupOrientationCollection>
</b:Popup.PreferredOrientations>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0">My popup's contents</TextBlock>
<Image Grid.Row="1" .... />
</Grid>
</Popup>
See the article Silverlight Popup with Target Placement
Download a project
What I do in this situation is to add a Grid or Border to the page that has a transparent background and IsHitTestVisible = True. You can then add your image etc to the parent control (Grid/Border).
You need to make sure the parent control covers the whole page and then just center the dialog inside this control. When you toggle the visibility of the parent control then the transparent background will overlay the other controls on the page, effectively disabling them.
Here is an example. The uxMessageGrid is the parent control and the Border is the actual dialog. You then just need to make sure this is the last control added to the root element and toggle uxMessageGrid.Visibility in your code.
<Grid x:Name="uxLayoutRoot">
<Other Controls />
<Grid x:Name="uxMessageGrid"
Visibility="Collapsed"
Background="Transparent"
IsHitTestVisible="True">
<Border CornerRadius="0"
BorderThickness="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
BorderBrush="{StaticResource PhoneForegroundBrush}"
Background="{StaticResource PhoneBackgroundBrush}">
<TextBlock Margin="15"
Text="Message..."
TextWrapping="Wrap"/>
</Border>
</Grid>
</Grid>
Use the Custom Dialog box features of the Coding4Fun toolkit
http://coding4fun.codeplex.com/
The toolkit has many controls available beyond the standard Silverlight Toolkit and should more than meet your needs.
Try this one, may be it helps to you
StackPanel st = new StackPanel();
StackPanel st1 = new StackPanel();
Image image = new Image();
image.Height = 300;
image.Width = 300;
image.Source = new BitmapImage(new Uri("/PhoneApp1;component/Koala.jpg", UriKind.Relative));//Build Action=Resource
Button btnok = new Button();
btnok.Content = "Ok";
btnok.Click += new RoutedEventHandler(btnok_Click);
Button btncancel = new Button();
btncancel.Content = "Cancel";
btncancel.Click += new RoutedEventHandler(btncancel_Click);
st1.Orientation = System.Windows.Controls.Orientation.Horizontal;
st1.Children.Add(btnok);
st1.Children.Add(btncancel);
st.Children.Add(image);
st.Children.Add(st1);
ContentPanel.Children.Add(st);