I'm using ScrollView in WPF, and my app allow user click on a button and then it will auto scroll the scrollview, I use ScrollToVerticalOffset() in button click event, but the scrollview not changed anything.
I searched about this issue on internet, but so far I can't not solve it yet.
And one more question: ScrollToVerticalOffset() take a double as parameter, it may will scroll to the special pixels, there any way to scroll to n items (not pixel)?
Here is my code
<ScrollViewer x:Name="scrollViewerChannelBtns" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center"
Background="Transparent" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden"
CanContentScroll="True" ScrollChanged="ScrollViewerChannelBtns_ScrollChanged">
<StackPanel x:Name="channelBtns" Orientation="Vertical">
<ItemsControl x:Name="channelBtnItems" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="tgbChannelName" Width="{Binding Path=ChannelNameBtnWidth}" Height="{Binding Path=ChannelNameBtnHeight}" HorizontalAlignment="Left" VerticalAlignment="Center" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Content="{Binding Path=ChannelName}" Tag="{Binding Path=Index}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
C# Code
//The button click event handled
private void BtnScrollDownClicked(object sender, RoutedEventArgs e)
{ scrollViewerChannelBtns.ScrollToVerticalOffset(scrollViewerChannelBtns.VerticalOffset + 50);
}
private void BtnScrollUpClicked(object sender, RoutedEventArgs e)
{ scrollViewerChannelBtns.ScrollToVerticalOffset(scrollViewerChannelBtns.VerticalOffset - 50);
}
Many thanks,
T&T
Mine is started work after;
ScrollViewer.UpdateLayout();
ScrollViewer.ScrollToVerticalOffset(outPoint.Y);
For me, this example works:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
<Grid>
<ScrollViewer x:Name="scrollViewerChannelBtns" HorizontalAlignment="Center" Height="100" CanContentScroll="False" VerticalAlignment="Center"
Background="Transparent" VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="channelBtns" Orientation="Vertical">
<ItemsControl x:Name="channelBtnItems">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="tgbChannelName" Width="40" Height="20" HorizontalAlignment="Left" VerticalAlignment="Center" IsChecked="{x:Null}" Content="Test" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<sys:String>Item 1</sys:String>
<sys:String>Item 2</sys:String>
<sys:String>Item 3</sys:String>
<sys:String>Item 4</sys:String>
<sys:String>Item 5</sys:String>
<sys:String>Item 6</sys:String>
<sys:String>Item 7</sys:String>
<sys:String>Item 8</sys:String>
<sys:String>Item 9</sys:String>
<sys:String>Item 10</sys:String>
</ItemsControl>
</StackPanel>
</ScrollViewer>
<Button Name="Up" Width="50" Height="30" VerticalAlignment="Top" Margin="110,0,0,0" Content="Up" Click="Up_Click" />
<Button Name="Down" Width="50" Height="30" VerticalAlignment="Top" Margin="210,0,0,0" Content="Down" Click="Down_Click" />
</Grid>
In the example I set the height for the ScrollViewer and CanContentScroll set false. Quote from answer why setting ScrollViewer.CanContentScroll to false disable virtualization:
ScrollViewer currently allows two scrolling modes: smooth pixel-by-pixel scrolling (CanContentScroll = false) or discrete item-by-item scrolling (CanContentScroll = true). Currently WPF supports UI virtualization only when scrolling by item. Pixel-based scrolling is also called “physical scrolling” and item-based scrolling is also called “logical scrolling”.
Virtualization requires item-based scrolling so it can keep track of logical units (items) currently in view... Setting the ScrollViewer to pixel-based scrolling their is no more concept of logic units but only pixels!
Code behind
private void Up_Click(object sender, RoutedEventArgs e)
{
scrollViewerChannelBtns.ScrollToVerticalOffset(scrollViewerChannelBtns.VerticalOffset - 50);
}
private void Down_Click(object sender, RoutedEventArgs e)
{
scrollViewerChannelBtns.ScrollToVerticalOffset(scrollViewerChannelBtns.VerticalOffset + 50);
}
Scrolling elements not supported by default, so you have to look at these links:
Consolidated Scrolling - "Pixel by Pixel" + "Item by Item"
ScrollViewer's Viewport Height VS Actual Height
Related
In a User Control I have below content:
<Grid>
<Popup x:Name="myPopup"
AllowsTransparency="True"
StaysOpen="False"
PlacementTarget="mouse"
Placement="Bottom">
<Grid>
<Rectangle MinWidth="40" Fill="#fff" Stroke="#BEBEBE"/>
<StackPanel Width="Auto" Height="Auto">
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="Bold"
Foreground="#666666"
Margin="12,15,12,0"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=someText}"
TextWrapping="Wrap"/>
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="SemiBold"
Foreground="#666666"
Margin="12,8,12,10"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=moreText}"
TextWrapping="Wrap" />
<Button x:Name="CloseBtn"
Content="Ok"
Background="White"
BorderBrush="#BEBEBE"
Foreground="Black"
HorizontalAlignment="Right"
Margin="5"
Padding="5"
Click="Close_Click"/>
</StackPanel>
</Grid>
</Popup>
</Grid>
This produces the follwowing window when button is shown:
and this another one when button is not shown:
The button in the window sometimes is visible and sometimes not (making it visible or collapsed respectively), it depends on some conditions. This is make visible or not in code-behind.
When the button is collapsed and not visible, the remaining space at the bottom of the window is removed as expected, the window resizes fine both its height and width according to its content. All works ok. This is just what I want, I mean, the window to be resizable to fit its content without leaving remaining whitespace areas. This is perfect.
Now, instead of a rectangle, I replace it with a path because I want it to be displayed as a speech bubble with an arrow pointing to the target. This path data is created dynamically at run time each time the stackpanel changes its size (I have added a SizeChanged event to the stack panel). See below how it is with this modification (Below code is the same as above but using a path instead of rectangle):
<Grid>
<Popup x:Name="myPopup"
AllowsTransparency="True"
StaysOpen="False"
PlacementTarget="mouse"
Placement="Bottom">
<Grid>
<!-- <Rectangle MinWidth="40" Fill="#fff" Stroke="#BEBEBE"/> -->
<Path x:Name="myPath" Visibility="Hidden"
Fill="White"
Stroke="#BEBEBE"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True">
</Path>
<StackPanel x:Name="stackpanel" Width="Auto" Height="Auto"
SizeChanged="StackPanel_SizeChanged">
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="Bold"
Foreground="#666666"
Margin="12,15,12,0"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=someText}"
TextWrapping="Wrap"/>
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="SemiBold"
Foreground="#666666"
Margin="12,8,12,10"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=moreText}"
TextWrapping="Wrap" />
<Button x:Name="CloseBtn"
Content="Ok"
Background="White"
BorderBrush="#BEBEBE"
Foreground="Black"
HorizontalAlignment="Right"
Margin="5"
Padding="5"
Click="Close_Click"/>
</StackPanel>
</Grid>
</Popup>
</Grid>
In the StackPanel_SizeChanged event I create a path Data in code-behind that then I associate to the path in the xaml view. The code in the StackPanel_SizeChanged event is the following:
private void StackPanel_SizeChanged(object sender, SizeChangedEventArgs e)
{
double width = e.NewSize.Width;
double height = e.NewSize.Height;
string stringPathData = $"M8,7.41 L15.415,0 L22.83,7.41 L{width},7.41 L{width},{height} L0,{height} L0,7.41 L8,7.41";
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Geometry));
this.myPath.Data = (Geometry)converter.ConvertFrom(stringPathData);
}
Path is drawn correctly around the window. But now the window does not adjust to fit its content. It fits the content width correctly but not the height. A whitespace area is kept at the bottom side of the window even when button is collapsed. See below:
I have observed that the window always keeps the largest height. I mean if I put some large text and after that a shorter text in the window, window maintains the largest height (in this case the first correponding to the large text) so this produces a whitespace are at the bottom side of the window. It looks like that when changing from a larger text to a shorter text the StackPanel_SizeChanged event does not get fired (well in fact it does not fire, I have debugged it). So I get the following independently if button is shown or not:
The close button event Close_Click is the following:
private void Close_Click(object sender, RoutedEventArgs e)
{
if (popup != null)
{
this.CloseBtn.Visibility = Visibility.Collapsed;
myPopup.IsOpen = false;
myPopup.StaysOpen = false;
}
}
I need the window to fit its content height and width.
PS. Please, if you have any doubts or questions or it is not clear for you, let me know before you spent your time reproducing it.
So the problem is, that the Stackpanel doesnt get rezised? In that case reloading the Popup when the text is changed should help.
Otherwise you could rezise the Popup manually which then resizes the Stackpanel (https://social.msdn.microsoft.com/Forums/vstudio/en-US/f98226ae-31d9-47da-a69a-687659378c94/how-to-resize-a-popup-in-wpf?forum=wpf).
I'm quite new to c# and WPF. I'm making a small Photo Viewer. I want to have a grid of photos in which I can change the number of columns and the size of the pictures depending on user preferences and the size of the screen. I can do everything I need at design time but I don't find how to change some properties during runtime.
In particular, I need to change the number of columns of the UniforGrid and the Width and Height of the Image.
<ListView x:Name="LVMiniaturasGrandes" Margin="23,10,464,270.5" Background="#FF272727" Foreground="White" Visibility="Hidden" BorderBrush="{x:Null}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ItemsControl Padding="10">
<StackPanel Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image Source="{Binding ImagenGrande2}" Width="200" Height="200" HorizontalAlignment="Stretch" VerticalAlignment="Top" Stretch="Uniform" />
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding NombreFichero}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Foreground="White" />
<TextBlock Text="{Binding VerEstrellas}" Foreground="Red" TextAlignment="Right" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
</StackPanel>
</StackPanel>
</ItemsControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I expect to be able both to change the number of columns and the height and width of the Image(s) depending on a slider control position and the actual pixel size of the screen.
Any help is welcome. Thanks in advance.
EDIT:
I've been able to modify the number of columns in the UniformGrid. It may not be very elegant but it works. But I'm still not able to access the Width and Height of the Images.
private void RejillaImagenesGrandes_Initialized(object sender, EventArgs e)
{
_UGImagenesGrandes = (UniformGrid)sender;
}
This way I can get access to the UniformGrid and modify the number of columns dynamically
I am wondering whether there is a better simpler way rewrite the following code find the closest parent which is a TabItem and remove it from the TabControl.
I have a TabControl where I add new TabItems dynamically. I assign a HeaderTemplate to each tab which looks like this;
<DataTemplate x:Key="AttorneyTabHeader">
<StackPanel Orientation="Horizontal">
<TextBlock Text="THE title" Margin="2,0,0,0" FontSize="16" VerticalAlignment="Center" />
<Button Width="Auto" UseLayoutRounding="False" BorderBrush="Transparent" Background="Transparent" Click="CloseAttorneysTabButtonClick">
<Image Source="/images/close-cross-thin-circular-button/close-cross-thin-circular-button16.png" Height="16"></Image>
</Button>
</StackPanel>
</DataTemplate>
The header has a close button and I would like to close the TabItem whenever the button is clicked. My click handler looks like this;
public void CloseAttorneysTabButtonClick(object sender, RoutedEventArgs e)
{
TabItem this_tab = (TabItem)((Button)sender).Parent.GetParentObject().GetParentObject().GetParentObject().GetParentObject().GetParentObject().GetParentObject();
AttorneysTabControl.Items.Remove(this_tab);
}
I am wondering whether there is a better way to rewrite this because now I am depending on getting the parent over and over again suppose I change the button and forget changing the handler.
There's probably a few ways you can handle it, but the simplest is likely to bind to the TabItem in the Tag property for the Button so that you can use it in your event handler.
<DataTemplate x:Key="TabHeaderTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="The Title" Margin="2 0 0 0" FontSize="16" VerticalAlignment="Center" />
<Button Width="Auto" UseLayoutRounding="False"
BorderBrush="Transparent" Background="Transparent"
Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}, Mode=OneWay}"
Click="Button_Click">
<Image Source="images/close.png" Height="16" />
</Button>
</StackPanel>
</DataTemplate>
Now your event handler can be relatively simple, and doesn't need to know as much as it does in your example.
void Button_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button && button.Tag is TabItem item) {
var tabControl = (TabControl)item.Parent;
tabControl.Items.Remove(item);
}
}
I'm new in XAML for Windows Phone 8.1 and have some troubles with
making a Stackpanel clickable
collapse Item, when clicked
My work so far looks like that:
And the Code to that (please correct me, if there are major flaws):
<Border CornerRadius="15" Background="#FF595656" Margin="0" Grid.ColumnSpan="2" Height="80">
<StackPanel Orientation="Horizontal">
<StackPanel Width="20" HorizontalAlignment="Left" VerticalAlignment="Top" />
<StackPanel HorizontalAlignment="Left" Height="80" Margin="0,0,0,0" VerticalAlignment="Center" Width="51">
<Image HorizontalAlignment="Left" Height="51" Margin="0,15,0,0" Width="51" Source="Assets/fish.png" Stretch="Fill" RenderTransformOrigin="2.307,0.881" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Width="10" HorizontalAlignment="Left" VerticalAlignment="Top" />
<StackPanel HorizontalAlignment="Left" Height="80" Margin="0" VerticalAlignment="Top" Width="310">
<TextBlock HorizontalAlignment="Left" Height="25" Margin="0,20,0,0" TextWrapping="Wrap" Text="Entry 1" Width="310" VerticalAlignment="Top" FontSize="18" Foreground="Black" FontWeight="Bold"/>
<TextBlock HorizontalAlignment="Left" Height="17" Margin="0" TextWrapping="Wrap" Text="Short description Entry 1" Width="310" VerticalAlignment="Top" Foreground="#FF0097FF"/>
</StackPanel>
</StackPanel>
</Border>
This code will later be wrapped inside a ListBox with Image, Entry 1 and the short description being bound:
<ListBox x:Name="ListBox1" Margin="0"
Width="400" Height="200" HorizontalAlignment="Left"
ItemsSource="{Binding}" Grid.Row="1" VerticalAlignment="Top" Grid.ColumnSpan="2" >
<ListBox.ItemTemplate>
<DataTemplate>
// the code above
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So my question is:
How can I make a nice looking expansion/collapse of each Item in the ListBox, whenever I click on it?
Thank you very much in advance.
The real question is here is what do you want it to collapse to? There are too many possible ways to collapse some visual data item. Do you just want to change the height of the item or do you want some fancy animation that collapse some property?
If the height is what you're looking for it's pretty easy. Just attach an Tap Event on that Border of yours. On a sidenote, you probably want to edit the ItemContainerStyle to have <Setter Property="HorizontalContentAlignment" Value="Stretch"/> so the Listbox will stretch across the screen, otherwise imho it's un-useable.
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="0,1" Tap="Border_Tap">
<StackPanel>
<!--- rest of template --->
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
Then calculate the Minimum height you want to show (make sure it's actually useable, meaning... I can Tap on it again to show the whole thing without using a Mag Glass).
private void Border_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
int minHeight = 40; // change to whatever you want
Border b = sender as Border;
if (b.ActualHeight > minHeight)
{
b.Height = minHeight;
}
else
{
b.Height = double.NaN; // this will change the height back to Auto, showing everything
}
}
Code In Action
This is just a quick solution to your question. Some people on here would rather have you create a StoryBoard Animation on the Height Property of the Selected state in the VisualStateManager. If you reword or create a new question explicitly stating you want a VisualStateManager solution, I will provide you one as well. Good luck.
I am trying to disable the right click functionality of my items inside a list view. I have tried handling the RightTapped event and setting the e.handled value to true. This has covered most of the list view's area however if I right click on the borders of the list view item, this selection style is still applied. I want the user to still be able to use the left click and apply the list selected styling. It is just the right click I want to disable.
Here is what I have tried so far:
<ListView
ItemsSource="{Binding MyItems}"
ItemClick="OnItemClicked"
IsItemClickEnabled="True"
SelectionMode="Multiple"
CanDragItems="True"
DragItemsStarting="OnDragItemsStarting"
RightTapped="OnRightTapped"
IsRightTapEnabled="False">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="-1,3,-1,0" />
<Setter Property="IsRightTapEnabled" Value="False"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent" RightTapped="OnRightTapped" HorizontalAlignment="Left" Height="100" Width="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding ImagePath}" Width="55" Height="55" Margin="0,0,0,1"/>
<Image Margin="20,0,0,22" Grid.Column="0" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="20" Height="20" Source="smallImage.png"/>
<StackPanel VerticalAlignment="Center" Margin="30,0,0,0" Grid.Column="1">
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" Foreground="{Binding IsOnline, Converter={StaticResource BooleanToColorConverter}}" Style="{StaticResource BaseTextBlockStyle}" FontSize="20" Height="60"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is the code for the RightTapped handler:
private void OnRightTapped(object sender, RightTappedRoutedEventArgs e)
{
e.Handled = true;
}
Edit: When I click on the borders of an Item in the ListView the OnRightTapped event is not being fired. What could be swallowing this event?
By playing with the background colors of the items inside my ListView.ItemTemplate, I found that my TextBlock was not covering the whole area of the row. By setting the Column width to the exact size of the ListView and setting the RightTapped event handler on this Grid I was able to cover all areas of right clicking. I still do not know why the RightTapped handler was not being fired for the ListView itself but this was a sufficient solution for what I needed.