Move Grid with Element Children - c#

i have this code as follows
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="one" Grid.Row="0" Margin="49.667,15,15,15">
<Grid x:Name="container1" Background="Red" Margin="10"/>
<TextBlock Text="1" FontSize="65" Margin="228,10,260,27"/>
</Grid>
<Button Content="mov" x:Name="first0" Click="first_Click" Foreground="White" HorizontalAlignment="Left" Margin="13.333,27.833,0,0" Width="29.334" Background="Black" Height="32" VerticalAlignment="Top"/>
<Grid x:Name="due" Grid.Row="1" Background="black" Margin="49.667,15,15,15">
<Grid x:Name="container2" Margin="12,12,8,8" Background="#FF618F36"/>
<TextBlock Text="2" FontSize="65" Margin="228,10,198,27"/>
</Grid>
</Grid>
and the code behind:
private static T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
private void first_Click(object sender, System.Windows.RoutedEventArgs e)
{
var first = FindVisualChild<Grid>(one);
var second = FindVisualChild<Grid>(due);
one.Children.Remove(first);
due.Children.Remove(second);
one.Children.Add(second);
due.Children.Add(first);
}
With this code i can move the "containers" in the Grid "one,due" but when i move the textblock disappear then i won't that ,because in future these grids will include others Grid,TextBox,textblock etc so kindly i ask you if there is a way to allow to move the containers including the childrens(textbox,textblock etc.)
Thank you in advance for the attention.
Sincerely

#Mark is right. The TextBlocks lie on top of your container grids, not inside them, which is why they don't move. Change your XAML to this, and it will work the way you expect:
...
<Grid x:Name="one" Grid.Row="0" Margin="49.667,15,15,15">
<Grid x:Name="container1" Background="Red" Margin="10">
<TextBlock Text="1" FontSize="65" Margin="228,10,260,27"/>
</Grid>
</Grid>
<Button ...
<Grid x:Name="due" Grid.Row="1" Background="black" Margin="49.667,15,15,15">
<Grid x:Name="container2" Margin="12,12,8,8" Background="#FF618F36">
<TextBlock Text="2" FontSize="65" Margin="228,10,198,27"/>
</Grid>
</Grid>
...

Related

Scrolling on a datagrid with ctrl button

I want my datagrid to only scroll with the mouse wheel when you press the ctrl key at the same time otherwise I want to scroll the page.
I am new to wpf and mvvm which is the pattern I use in my application.
That's the page that contains the datagrid:
<Page x:Class="Projectname.ChapterPage"
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"
xmlns:local="clr-namespace:Projectname"
xmlns:core="clr-namespace:Projectname.Core;assembly=Projectname.Core"
mc:Ignorable="d"
d:DesignHeight="700" d:DesignWidth="900"
Title="ChapterPage">
<StackPanel>
<TextBlock Grid.Column="0"
Grid.ColumnSpan="2"
Text="Kapitel"
Style="{StaticResource HeaderText}"
Foreground="{StaticResource
ForegroundVeryLightBrush}"
FontSize="{StaticResource FontSizeLarge}"
FontWeight="Bold"
Margin="50 -45 50 15"/>
<Border Background="{StaticResource BlueBrush}"
CornerRadius="10"
Margin="10"
MinHeight="45"
Padding="2">
<StackPanel HorizontalAlignment="Center"
Orientation="Horizontal">
<Button Command="{Binding SaveCommand}"
Style="{StaticResource IconGrowButton}"
ToolTip="Speichern"
Margin="10 0"
MaxHeight="30"
MinWidth="30"
Cursor="Hand">
<Image Source="../Images/Icons/Save.png" />
</Button>
<Button Command="{Binding DeleteCommand}"
Style="{StaticResource IconGrowButton}"
ToolTip="Löschen"
MaxHeight="30"
MinWidth="30"
Margin="10 0 80 0"
Cursor="Hand">
<Image Source="../Images/Icons/Delete.png" />
</Button>
<Button Command="{Binding ResetCommand}"
Style="{StaticResource IconGrowButton}"
ToolTip="Zurücksetzen"
MaxHeight="30"
MinWidth="30"
Margin="10 0"
Cursor="Hand">
<Image Source="../Images/Icons/Reset.png" />
</Button>
</StackPanel>
</Border>
<DataGrid Margin="15 10"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Chapters,
UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding ChaptersVisibility,
Converter={local:BooleanToVisibilityConverter}}"
SelectedItem="{Binding SelectedChapter}"/>
</StackPanel>
</Page>
My page is loaded into a window and the scrollviewer to scroll the content is in the window.
That is the window:
<Grid>
<StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Background="{StaticResource RedBrush}">
<Button Command="{Binding NavMenuCommand}"
Style="{StaticResource SystemIconButton}"
Cursor="Hand"
HorizontalAlignment="Left">
<Button.Content>
<Image Source="../Images/Icons/burger-
menue.png"
Height="25"/>
</Button.Content>
</Button>
</Border>
</Grid>
<local:ChapterPage
Padding="8 0"/>
</StackPanel>
<local:NavMenu Margin="0,41,628,0"/>
</Grid>
</ScrollViewer>
I have absolutely no idea how to achieve this but I don't want to use the xaml.cs if I can avoid it.
The reason I want the different scrolling behavior is because there is a big user control between the data grid and the header area. Here is a picture of the division of the page.
You need to handle the PreviewMouseWheel event by the common parent of both or all participating ScrollViewer :
MainWindow.xaml
Simplified view:
<Window PreviewMouseWheel="HandleScroll_OnPreviewMouseWheel">
<ScrollViewer x:Name="RootScrollViewer">
<DataGrid x:Name="DataGridToScrollOnKeyPress" />
</ScrollViewer>
</Window>
MainWindow.xaml.cs
private ScrollViewer DataGridScrollViewer { get; set; }
private void OnLoaded(object sender, RoutedEventArgs e)
{
// Find DataGrid by name (in case of multiple DataGrids)
if (TryFindVisualChildElement(this.Root, "DataGridToScrollOnKeyPress", out DataGrid dataGrid))
{
// And get its ScrollViewer (by type)
if (TryFindVisualChildElement(dataGrid, string.Empty, out ScrollViewer scrollViewer))
{
this.DataGridScrollViewer = scrollViewer;
}
}
}
private void HandleScroll_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
// Give the main scroll viewer chance to handle its own scroll,
// if it is the scroll source (preserve default behavior)
if (e.Source == this.Root
&& !Keyboard.IsKeyDown(Key.LeftCtrl)
&& !Keyboard.IsKeyDown(Key.RightCtrl))
{
return;
}
e.Handled = true;
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
if (e.Delta < 0)
{
this.DataGridScrollViewer?.LineDown();
}
else
{
this.DataGridScrollViewer?.LineUp();
}
}
else // Some other control is scroll source => scroll main scroll viewer
{
if (e.Delta < 0)
{
this.RootScrollViewer.LineDown();
}
else
{
this.RootScrollViewer.LineUp();
}
}
}
// If the 'childElementName' parameter is NULL, an empty string or whitespace it will be ignored (only the type will be relevant)
public bool TryFindVisualChildElement<TChild>(DependencyObject parent, string childElementName, out TChild childElement)
where TChild : FrameworkElement
{
childElement = null;
if (parent == null)
{
return false;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TChild resultElement
&& (string.IsNullOrWhiteSpace(childElementName) || resultElement.Name.Equals(childElementName, StringComparison.Ordinal)))
{
childElement = resultElement;
return true;
}
if (TryFindVisualChildElement(child, childElementName, out childElement))
{
return true;
}
}
return false;
}

display a UserControl when click Button

I have created a ListViewTemplate as a UserControl,that I want to display it when I click on this Hamburger Button,this is my code:
Main.xaml:
<SplitView.Content >
<Grid Background="White" >
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#f0f0f0" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="TrieButton" Margin="0" Content=""
Width="50" Background="Transparent" VerticalAlignment="Stretch" Click="TrieButton_Click" />
</StackPanel>
</Grid>
<Frame Grid.Row="1" x:Name="ContentFrame" Margin="0" />
</Grid>
</SplitView.Content>
And this is the code Behind:
Main.xaml.cs:
private void TrieButton_Click(object sender, RoutedEventArgs e)
{
ListViewTemplate c = new ListViewTemplate();
if (c.Visibility == Visibility.Visible)
{
c.Visibility = Visibility.Collapsed;
}
else
{
c.Visibility = Visibility.Visible;
}
}
this is my UserControl:
ListViewTemplate.xaml:
<Grid x:Name="FilterGrid" Background="Black">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0" >
<ListView x:Name="Liste" Background="Black" >
<ListViewItem >
<TextBlock Text="Nom" Foreground="#9d9e9e"/>
</ListViewItem>
<ListViewItem >
<TextBlock Text="Catégorie" Foreground="#9d9e9e"/>
</ListViewItem >
</ListView>
</StackPanel>
</Grid>
My problem is that this ListView UserControl is not shown when I click on the TrieButton,even I have increased the height of Grid
so please How can I correct my code,to have Listview showed when I click on TrieButton
thanks for help
Firstly: You didn't add the UserControl to your main XAML anywhere. You should add to XAML first like this:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:usercontrol="clr-namespace:WpfApplication1"
Then:
<Grid Background="White" x:Name="MGrid">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="10" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#f0f0f0" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="TrieButton" Margin="0" Content=""
Width="50" Background="Transparent" VerticalAlignment="Stretch" Click="TrieButton_Click" />
</StackPanel>
</Grid>
<Frame Grid.Row="1" x:Name="ContentFrame" Margin="0" />
<usercontrol:ListViewTemplate x:Name="c" Grid.Row="2" Visibility="Collapsed"></usercontrol:ListViewTemplate>
</Grid>
Secondly: You just created a new instance of a ListViewTemplate. You should find one that is placed in your XAML by using FindName method and then change the Visibility of it like this:
private void TrieButton_Click(object sender, RoutedEventArgs e)
{
ListViewTemplate c = MGrid.FindName("c") as ListViewTemplate;
c.Visibility = c.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
}
In response to the button click you are incorrectly creating a new instance of a ListViewTemplate object and then throwing it away.
I think that what you really want to do is something along these lines:
private void TrieButton_Click(object sender, RoutedEventArgs e)
{
ListViewTemplate c = (ListViewTemplate) Controls["Liste"];
if (c.Visibility == Visibility.Visible)
c.Visibility = Visibility.Collapsed;
else
c.Visibility = Visibility.Visible;
}
Here we retrieve the existing Control and change its visible/collapsed state.

Windows phone 8 ListBox becomes empty after loading a lot of data

In my WP8 application I have a listbox which performs Lazy load. All is working fine except one thing. Sometimes after scrolling up or down, even when data is the same, my listbox becomes empty. I analized the used memory using "Windows phone application analyses" and got the maximum used memory 100MB. So there is no problem with memory. Also aplication does not crash after becoming listbox empty. Do you have any ideas why these happen?
Here is my XAML:
<ListBox Name="lbCollections" LayoutUpdated="lbCollectins_LayoutUpdated">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Background="White" Margin="20">
<Grid Margin="15,5,15,5">
<Grid.RowDefinitions>
<RowDefinition Height="45"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text="{Binding CategoryName}" Foreground="Black" Style="{StaticResource EmptyListHeaderStyle}"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding CreatedOn, StringFormat='{}{0:MM dd, yyyy}'}" Foreground="Gray" Style="{StaticResource PhoneTextSmallStyle}"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding PhotosCountTxt}" Foreground="Gray" Style="{StaticResource PhoneTextSmallStyle}"></TextBlock>
</Grid>
<Grid Height="150">
<Grid.Resources>
<conv:ImageConverter x:Key="ImageConverter" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Name="img1" Source="{Binding Photos, Converter={StaticResource ImageConverter}, ConverterParameter=0}" Width="150" Height="150" Margin="5"/>
<Image Grid.Column="1" Name="img2" Source="{Binding Photos, Converter={StaticResource ImageConverter}, ConverterParameter=1}" Width="150" Height="150" Margin="5"></Image>
<Image Grid.Column="2" Name="img3" Source="{Binding Photos, Converter={StaticResource ImageConverter}, ConverterParameter=2}" Width="150" Height="150" Margin="5"></Image>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Here is the code behind:
private async void LoadContent()
{
if (loadingProgress)
{
return;
}
else
{
try
{
loadingProgress = true;
CollectionResponse collectionResp = await CollectionService.IterateAsync(MapPoint, "", dtStart, dtEnd, filterCategoryId, loadedCollectionsCount, collectionsCountToLoadAtOnce, 4, (int)TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes, AppSettings.Invisible, AppSettings.Token);
if (collectionResp.Collections.Count == 0)
{
endOfList = true;
}
else
{
loadedCollectionsCount += collectionResp.Collections.Count;
if (!(lbCollections.ItemsSource is List<CollectionModel>))
{
lbCollections.ItemsSource = new List<CollectionModel>();
}
(lbCollections.ItemsSource as List<CollectionModel>).AddRange(collectionResp.Collections);
//lbCollections.ItemsSource = collectionResp.Collections;
}
}
catch
{
}
finally
{
loadingProgress = false;
}
}
}
private void lbCollectins_LayoutUpdated(object sender, EventArgs e)
{
ScrollBar scrollBar = FindChildOfType<ScrollBar>(lbCollections).Where(sb=>sb.Orientation == System.Windows.Controls.Orientation.Vertical).FirstOrDefault();
if (scrollBar != null)
{
bool endOfScroll = scrollBar.Maximum > 0 && scrollBar.Value > 0 && scrollBar.Maximum - scrollBar.Value < 10;
if (!endOfList && endOfScroll)
{
LoadContent();
}
}
}
static List<T> FindChildOfType<T>(DependencyObject root) where T : class
{
List<T> foundObjects = new List<T>();
var queue = new Queue<DependencyObject>();
queue.Enqueue(root);
while (queue.Count > 0)
{
DependencyObject current = queue.Dequeue();
for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; i >= 0; i--)
{
var child = VisualTreeHelper.GetChild(current, i);
var typedChild = child as T;
if (typedChild != null)
{
foundObjects.Add(typedChild);
}
queue.Enqueue(child);
}
}
return foundObjects;
}
Two things to do.
Take a look at this blog about why the ListBox goes blank. Most likely the problem is the images you are showing. You can easily fix by doing the following
Start using the LongListSelector for WP8 (not the WP Toolkit version!) It is designed for fast scrolling even with images

How to access a Control inside the data template in C# Metro UI in the code behind

I have a MediaElement that resides inside the datatemplate of flipview, i want to access that MediaElement named "video" in the code behind so that i can assign properties like play, pause, etc to through buttons
here is the code of what i'm trying to do :
<FlipView
x:Name="flipView"
AutomationProperties.AutomationId="ItemsFlipView"
AutomationProperties.Name="Item Details"
TabIndex="1"
Grid.RowSpan="2"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}">
<FlipView.ItemContainerStyle>
<Style TargetType="FlipViewItem">
<Setter Property="Margin" Value="0,137,0,0"/>
</Style>
</FlipView.ItemContainerStyle>
<FlipView.ItemTemplate>
<DataTemplate>
<UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
<ScrollViewer x:Name="scrollViewer" Style="{StaticResource VerticalScrollViewerStyle}" Grid.Row="1">
<Grid Margin="120,0,20,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="360" />
<ColumnDefinition Width="40" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" BorderThickness="1" Width="350" HorizontalAlignment="Left" Grid.Row="0">
<MediaElement x:Name="Video" AutomationProperties.Name="Video" Source="/Assets/Big_Buck_Bunny.mp4" HorizontalAlignment="Center" VerticalAlignment="Stretch" Height="250" Width="350" AutoPlay="True" IsLooping="True" />
</Border>
<Border BorderBrush="Black" BorderThickness="1" Height="65" Width="350" HorizontalAlignment="Left" Grid.Row="1">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="playButton" Margin="0,0" Click="playButton_Click" Style="{StaticResource PlayAppBarButtonStyle}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="pauseButton" Margin="0,0" Click="pauseButton_Click" Style="{StaticResource PauseAppBarButtonStyle}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</Grid>
</ScrollViewer>
</UserControl>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
How do i achieve the intended ?
Try the following:
private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
{
int childNumber = VisualTreeHelper.GetChildrenCount(control);
for (int i = 0; i < childNumber; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(control, i);
FrameworkElement fe = child as FrameworkElement;
// Not a framework element or is null
if (fe == null) return null;
if (child is T && fe.Name == ctrlName)
{
// Found the control so return
return child;
}
else
{
// Not found it - search children
DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
if (nextLevel != null)
return nextLevel;
}
}
return null;
}
Then call it from the play / pause button button:
MediaElement media = FindChildControl<MediaElement>(this, "media") as MediaElement;
media.Play();
A related blog post on the subject
I wrote a blog article on this very topic about a year ago. Perhaps it will help you: http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html
The gist is this. You must parse through the visual tree to get all elements, and then you can use something like LINQ to filter the results and get your objects.
I extended Jerry's solution to a more flexible and better performance solution in getting only desired controls and do not create intermediated Lists during recursive calls.
You can simply using like that to get the control:
var myControl = AllChildren(parent, c => c.Name == "xxx").FirstOrDefault();
For that you should include the following AllChildren funcion:
private List<Control> AllChildren(DependencyObject parent, Func<DependencyObject, bool> query, List<Control> _List = null )
{
if (_List == null)
_List = new List<Control>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var _Child = VisualTreeHelper.GetChild(parent, i);
if (_Child is Control && query(_Child))
{
_List.Add(_Child as Control);
}
AllChildren(_Child, query, _List);
}
return _List;
}

Mouse scroll not working in a scroll viewer with a wpf datagrid and additional UI elements

I am trying to figure out how to get the mouse scroll working on a wpf window with a scrollviewer and a datagrid within it. The WPF and C# code is below
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Border Name="DataGridBorder" BorderThickness="2" Margin="1" CornerRadius="4" BorderBrush="#FF080757">
<dg:DataGrid AutoGenerateColumns="False" Name="ValuesDataGrid"
BorderThickness="0" CanUserResizeColumns="True" FontWeight="Bold" HorizontalScrollBarVisibility="Auto"
CanUserReorderColumns="False" IsReadOnly="True" IsTextSearchEnabled="True" AlternationCount="2"
SelectionMode="Extended" GridLinesVisibility="All"
HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" CanUserSortColumns="False"
RowDetailsVisibilityMode="Collapsed" SelectedIndex="0"
RowStyle="{StaticResource CognitiDataGridRowStyle}"
>
<dg:DataGrid.Columns>
<dg:DataGridTemplateColumn Header="Title" >
<dg:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Path=Name}" FontWeight="Normal" />
</StackPanel>
</DataTemplate>
</dg:DataGridTemplateColumn.CellTemplate>
</dg:DataGridTemplateColumn>
</dg:DataGrid.Columns>
</dg:DataGrid>
</Border>
</Grid>
<Button Grid.Row="1" Height="90" >hello world</Button>
</Grid>
</ScrollViewer>
and the C# code is as follows
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
initialize();
}
public void initialize()
{
ObservableCollection<MyObject> testList = new ObservableCollection<MyObject>();
for (int i = 0; i < 20; i++)
{
MyObject my = new MyObject("jack " + i);
testList.Add(my);
}
ValuesDataGrid.ItemsSource = testList;
}
}
public class MyObject
{
public string Name { get; set; }
public MyObject(string name)
{
Name = name;
}
}
The problem i am facing is that when using the mouse to scroll, it works fine when it is over the button but as soon as i move the mouse pointer over the grid and try to scroll, nothing happens. I am able to move the scrollbar of the scrollviewer directly though. I am still a wpf novice so any help on how to get the mouse scroll to work over the datagrid would be appreciated. I am guessing there should be a pretty easy solution for this but I havent been able to figure it out
I think Dave's solution is a good one. However, one recommendation I'd make is to catch the PreviewMouseWheel event on the scrollviewer instead of on the datagrid. If you don't, you might notice some minor differences based on whether you're scrolling over the datagrid or the scroll bar itself. The reasoning is that the scrollviewer will be handling scrolling when the mouse is hovered over the scrollbar, and the datagrid event will handle the scrolling when over the datagrid. For instance, one mouse wheel scroll over the datagrid might bring you farther down your list then it would when over the scroll bar. If you catch it on scrollviewer preview event, all will use the same measurement when scrolling. Also, if you catch it this way, you won't need to name the scrollviewer element, as you won't need a reference to the object since you can just type cast the sender object passed into the scrollviewer PreviewMouseWheel event. Lastly, I'd recommend marking the event handled at the end of the event, unless you need to catch it in an element further down the heirarchy for some reason. Example below:
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ScrollViewer scv = (ScrollViewer)sender;
scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
e.Handled = true;
}
I'm assuming the DataGrid does not need to scroll - Set the VerticalScrollBar="None" on the DataGrid.
The DataGrid swallows the mouse scroll event.
What I found is to use the PreviewMouseWheel event to scroll the container that you want to scroll. You will need to name the scrollviewer to change the Vertical offset.
private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset-e.Delta);
}
An improvement to Don B's solution is to avoid using ScrollToVerticalOffset.
scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
VerticalOffset - Delta results in a pretty jarring experience. The ScrollViewer puts a lot of thought into making the movement smoother than that. I think it also scales the delta down based on dpi and other factors...
I found it's better to catch and handle the PreviewMouseWheelEvent and send a MouseWheelEvent to the intended ScrollViewer. My version of Don B's solution looks like this.
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
eventArg.RoutedEvent = UIElement.MouseWheelEvent;
eventArg.Source = e.Source;
ScrollViewer scv = (ScrollViewer)sender;
scv.RaiseEvent(eventArg);
e.Handled = true;
}
To enable touch support you might also want to set ScrollViewer.PanningMode to None on your DataGrid and set the same property to VerticalFirst or other value on your top level ScrollViewer
Example
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst">
<DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" />
</ScrollViewer>
Of course, also use the PreviewMouseWheel event as indicated by Don B's answers to fix the original mouse scrolling issue.
private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
e.Handled = true;
}
Or, you can simply set the following Attached Property to your ScrollViewer
public class TopMouseScrollPriorityBehavior
{
public static bool GetTopMouseScrollPriority(ScrollViewer obj)
{
return (bool)obj.GetValue(TopMouseScrollPriorityProperty);
}
public static void SetTopMouseScrollPriority(ScrollViewer obj, bool value)
{
obj.SetValue(TopMouseScrollPriorityProperty, value);
}
public static readonly DependencyProperty TopMouseScrollPriorityProperty =
DependencyProperty.RegisterAttached("TopMouseScrollPriority", typeof(bool), typeof(TopMouseScrollPriorityBehavior), new PropertyMetadata(false, OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var scrollViewer = d as ScrollViewer;
if (scrollViewer == null)
throw new InvalidOperationException($"{nameof(TopMouseScrollPriorityBehavior)}.{nameof(TopMouseScrollPriorityProperty)} can only be applied to controls of type {nameof(ScrollViewer)}");
if (e.NewValue == e.OldValue)
return;
if ((bool)e.NewValue)
scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel;
else
scrollViewer.PreviewMouseWheel -= ScrollViewer_PreviewMouseWheel;
}
private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
e.Handled = true;
}
}
Usage
<ScrollViewer b:TopMouseScrollPriorityBehavior.TopMouseScrollPriority="True" VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst">
<DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" />
</ScrollViewer>
Where b: is the namespace that contains this behavior
This way your no code-behind is needed and your app is purely MVVM
I tried Don B's solution and it's solves the issue with scrolling over a data grid pretty well for the cases when you don't have other inner scrollable controls.
For the case when the scroll viewer has as children other scrollable controls and a data grid, then that requires that the event shouldn't be marked as handled at the end of the event handler for the main scroll viewer so it could be catched also in the inner scrollable controls, however that has the side effect that when the scroll should occur only on the inner scrollable control, it will also occur on the main scroll viewer.
So I've updated Dave's solution with the difference for how the scroll viewer is found so it won't be necessary to know the name of the scroll viewer:
private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ScrollViewer scrollViewer = (((DependencyObject)sender).GetVisualParent<ScrollViewer>());
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
}
#fjch1997, I used your solution and it works pretty well.
There is only one problem which I found. It's connected with the comment of #Vadim Tofan:
For the case when the scroll viewer has as children other scrollable
controls and a data grid, then that requires that the event shouldn't
be marked as handled at the end of the event handler for the main
scroll viewer so it could be catched also in the inner scrollable
controls, however that has the side effect that when the scroll should
occur only on the inner scrollable control, it will also occur on the
main scroll viewer.
I also tried to remove e.Handled = true statement, but then the effect is not nice - both scrolls are moved in the same time. So, finally I enhanced a little bit event handler method to the following one:
private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
ScrollViewer scrollViewer = (ScrollViewer)sender;
FrameworkElement origicalControlSender = e.OriginalSource as FrameworkElement;
ScrollViewer closestScrollViewer = origicalControlSender.GetParent<ScrollViewer>();
if (closestScrollViewer != null && !ReferenceEquals(closestScrollViewer, scrollViewer))
{
return;
}
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
e.Handled = true;
}
public static T GetParent<T>(this FrameworkElement control)
where T : DependencyObject
{
FrameworkElement parentElement = control?.Parent as FrameworkElement;
if (parentElement == null)
{
return null;
}
T parent = parentElement as T;
if (parent != null)
{
return parent;
}
return GetParent<T>(parentElement);
}
This now prevents the outside scroller to scroll in case inner ScrollViewer exists.
Guys I`ve seen most of the solution posted over here and fundamentally all of them are right, but I think there is an easiest and more elegant syntax that we could apply.
Assuming that we don't need to scroll with our data grid and instead we would like to scroll with our MainWindow
fallowing "Dave" and "Vladim Tofan" answer
Private Void Scrlll(Object sebder, MouseWheelEventArgs e)
{
var windows = (Window.GetWindow(this) as MainWindow).MainScroll;
windows.ScrollToVerticalOffset(windows.VerticalOffset - e.Delta);
}
Sorry, for bad english.
Here is a larger example of creating a WPF behavior that scrolls the DataGrid.
First define the following base class for gluing together framework element with behavior class and its behavior implementation.
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Input;
namespace SomeAcme.Client.Infrastructure
{
/// <summary>
/// Behavior handler class for creating WPF behaviors.
/// </summary>
[ExcludeFromCodeCoverage]
public class BehaviorHandler<TAssociatedObject, TBehaviorClass>
where TAssociatedObject: DependencyObject
where TBehaviorClass : class, IAssociationBehavior, new()
{
public BehaviorHandler()
{
}
public static TBehaviorClass GetBehavior(DependencyObject obj)
{
if (obj == null)
return null;
return (TBehaviorClass)obj.GetValue(BehaviorProperty);
}
public static void SetBehavior(DependencyObject obj, TBehaviorClass value)
{
if (obj != null)
{
obj.SetValue(BehaviorProperty, value);
}
}
// Using a DependencyProperty as the backing store for Behavior. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BehaviorProperty =
DependencyProperty.RegisterAttached("Behavior", typeof(TBehaviorClass), typeof(object), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
public void FindOrCreateBehaviorOnDemand(DependencyObject dependencyObject)
{
//Apply the behavior
TBehaviorClass behavior = FindOrCreateBehavior(dependencyObject);
if (behavior != null)
{
dependencyObject.SetValue(BehaviorProperty, behavior);
}
}
public TBehaviorClass FindOrCreateBehavior(DependencyObject dependencyObject)
{
if (dependencyObject == null)
return null;
var associatedObject = dependencyObject;
if (associatedObject == null)
return null;
var behavior = dependencyObject.GetValue(BehaviorProperty) as TBehaviorClass;
if (behavior == null)
{
var behaviorAssociated = new TBehaviorClass();
if (behaviorAssociated == null)
return null;
behaviorAssociated.InitializeAssociation(associatedObject, AssociatedCommands);
return behaviorAssociated;
}
else
{
return behavior;
}
} //TBehaviorClass FindOrCreateBehavior
/// <summary>
/// Set the associated commands to pass into the WPF behavior, if desired
/// </summary>
public ICommand[] AssociatedCommands { get; set; }
}
}
This looks a bit more complex, but it simplifies boiler plate coding when it comes to gluing together the behavior class with the framework element. In this particular case we will not need to use an associated command.
Our scroll viewer behavior then looks like this:
using SomeAcme.Client.Infrastructure;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SomeAcme.Client.Infrastructure
{
public static class ScrollViewerMouseWheelScrollBehavior
{
public static string GetUseMouseScrollForScrollViewer(DependencyObject obj)
{
if (obj != null)
{
return (string)obj.GetValue(UseMouseScrollForScrollViewerProperty);
}
else
return null;
}
public static void SetUseMouseScrollForScrollViewer(DependencyObject obj, string value)
{
if (obj != null)
{
obj.SetValue(UseMouseScrollForScrollViewerProperty, value);
}
}
public static readonly DependencyProperty UseMouseScrollForScrollViewerCommandProperty =
DependencyProperty.RegisterAttached("UseScrollForScrollViewer", typeof(string), typeof(ScrollViewerMouseWheelScrollBehavior),
new PropertyMetadata(new PropertyChangedCallback(OnUseScrollForScrollViewerSet)));
public static void OnUseScrollForScrollViewerSet(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
{
bool useScroll;
bool.TryParse(eventArgs.NewValue?.ToString(), out useScroll);
if (useScroll)
{
var behaviorHandler =
new BehaviorHandler<ScrollViewer, ScrollViewerMouseScrollBehaviorImplementation>();
//behaviorHandler.AssociatedCommands =
// new Microsoft.Practices.Prism.Commands.DelegateCommand<object>[] { (Microsoft.Practices.Prism.Commands.DelegateCommand<object>)eventArgs.NewValue };
behaviorHandler.FindOrCreateBehaviorOnDemand(dependencyObject);
}
}
}
}
namespace SomeAcme.Client.Infrastructure
{
public class ScrollViewerMouseScrollBehaviorImplementation : IAssociationBehavior
{
public void InitializeAssociation(DependencyObject associatedObject, params ICommand[] commands)
{
//TODO: Add commands to associate
var scrollViewer = associatedObject as ScrollViewer;
if (scrollViewer != null)
{
scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel;
}
}
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var scrollViewer = sender as ScrollViewer;
if (scrollViewer != null)
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
}
}
}
}
In XAML we then can first define the namespaces:
xmlns:local="clr-namespace:SomeAcme.Client.Infrastructure"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Finally we are ready to use the mouse wheel scroll by using the WPF behavior in the XAML.
..
<TabControl Grid.Row="1">
<TabItem Header="Skjemafelter">
<ScrollViewer Height="700" local:ScrollViewerMouseWheelScrollBehavior.UseMouseScrollForScrollViewer="{x:Static sys:Boolean.TrueString}">
<ListView x:Name="ColumnsListView" ItemsSource="{Binding CurrentFields}">
<ListView.View>
<GridView>
I have tested and verified that this approach works. For developers working with a WPF app, utilizing WPF behaviors keeps amount of code in code behind still to the minimum bits and staying faitfully to the MVVM approach.
The Grid has a built in ScrollPanel so wrapping it with a ScrollPanel didn't work at all for me (making the Grid of fixed height was out of the question because I wanted it to resize nicely with the rest of the application).
What I did was a combination of a few of the higher rated solutions in here, but essentially the idea is to get rid of the ScrollPanel and just pipe the PreviewMouseEvent of the DataGrid back to the parent control that is actually handling the scrolling (in my case it was a Grid).
private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
MouseWheelEventArgs eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
RoutedEvent = MouseWheelEvent, Source = e.Source
};
DependencyObject parent = VisualTreeHelper.GetParent((DependencyObject) sender);
while (parent != null && !(parent is Grid))
{
parent = VisualTreeHelper.GetParent(parent);
}
if (parent != null)
{
Grid grid = (Grid) parent;
grid.RaiseEvent(eventArg);
}
e.Handled = true;
}
I found this: http://wpfthoughts.blogspot.com/2014/05/datagrid-vertical-scrolling-issues.html and thought I should add it here.
"If you are targeting Framework 4.5 there is a new dependency object on the DataGrid's internal VirtualizingPanel called ScrollUnit that can be set to Item (the default) or Pixel. If we modify the XAML a little we can see how it works."
<DataGrid Name="DG" ItemsSource="{Binding B0}" AutoGenerateColumns="False" IsReadOnly="true" RowDetailsVisibilityMode="Visible" Width="200"
Height="100" VirtualizingPanel.ScrollUnit="Pixel">
I know it's been a while, but I met the same issue and solved it with DockPanel
<DockPanel Grid.ColumnSpan="3" LastChildFill="True">
<Button DockPanel.Dock="Top" Content="Add" Grid.Column="3" HorizontalAlignment="Right" Width="110" Height="30" Margin="5"/>
<DataGrid x:Name="xxDG" SelectionUnit="Cell" ItemsSource="{Binding}" Margin="0, 0, 0, 0" >
...
</DataGrid>
</DockPanel>
For some reason this handles the mouse wheel events like a charm.
I found that ScrollViewer can't be concatenated, which means if it is concatenated like in your case the Grid starts under the ScrollViewer tag and in the Grid we have DataGrid and in the DataGrid again the ScrollViewer property has been set. i.e.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="45" />
<RowDefinition Height="100*" />
<RowDefinition Height="105" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0"
Grid.Column="0"
Margin="10,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Vessel: " />
<TextBox Height="30"
Width="300"
Margin="70,0,0,0"
HorizontalAlignment="Left"
BorderThickness="1,1,1,1"
IsReadOnly="True"
Name="txtVessel" />
<Label Grid.Row="0"
Grid.Column="2"
Margin="0,0,185,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Month:" />
<StackPanel Orientation="Horizontal"
Grid.Row="0"
Grid.Column="2"
Margin="0,0,0,0"
HorizontalAlignment="Right">
<ComboBox BorderThickness="2"
HorizontalAlignment="Right"
Name="CmbMonth"
VerticalAlignment="Center"
Width="90" />
<ComboBox BorderThickness="2"
HorizontalAlignment="Right"
Margin="5,0,0,0"
Name="CmbYear"
VerticalAlignment="Center"
Width="90" />
</StackPanel>
<Grid Grid.Row="1"
Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="45" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="220" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="140*" />
</Grid.ColumnDefinitions>
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="0" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="1" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="2" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="3" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="4" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="5" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="6" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="7" />
<Border BorderBrush="Black"
BorderThickness="0,1,1,1"
Grid.Row="0"
Grid.Column="8" />
<Label Grid.Row="0"
Grid.Column="1"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Item" />
<Label Grid.Row="0"
Grid.Column="2"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Maker" />
<Label Grid.Row="0"
Grid.Column="3"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Model" />
<Label Grid.Row="0"
Grid.Column="4"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content=" Part No.
Serial No." />
<Label Grid.Row="0"
Grid.Column="5"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Condition" />
<Label Grid.Row="0"
Grid.Column="6"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content=" Onboard
Calibr/Test" />
<Label Grid.Row="0"
Grid.Column="7"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content=" Shore
Callibration" />
<Label Grid.Row="0"
Grid.Column="8"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Remarks" />
</Grid>
<Border Grid.Row="2"
Grid.ColumnSpan="2">
<ScrollViewer Grid.Row="2"
Grid.ColumnSpan="2"
CanContentScroll="True"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Name="ScrollViewer3"
Margin="0,0,0,0">
<Grid Name="grdOnBoardCalibrationRecord"
Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"></ColumnDefinition>
<ColumnDefinition Width="220"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="120"></ColumnDefinition>
<ColumnDefinition Width="120"></ColumnDefinition>
<ColumnDefinition Width="140*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0"
BorderThickness="1,0,1,1"
BorderBrush="Black"
Grid.RowSpan="26"></Border>
<Border Grid.Column="1"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="2"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="3"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="4"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="5"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="6"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="7"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
<Border Grid.Column="8"
BorderThickness="0,1,1,1"
Grid.RowSpan="26"></Border>
</Grid>
</ScrollViewer>
</Border>
<Grid Grid.Row="3"
Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0"
Grid.Column="0"
Height="30"
Width="300"
TextAlignment="Center"
Background="Gray"
IsReadOnly="True"
Margin="0,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
BorderThickness="1,1,1,1"
Name="txtChiefEngineer" />
<Label Grid.Row="1"
Grid.Column="1"
Margin="0,0,100,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontWeight="Bold"
Content="Chief Engineer" />
<StackPanel Orientation="Horizontal"
Grid.Row="2"
Margin="0,0,0,0">
<Label Name="lblonshorecomment"
Content=" Shore Comment : "
HorizontalAlignment="Center"
Margin="5,0,0,0"
FontWeight="Bold"
VerticalAlignment="Center"
FontFamily="Calibri"
FontStyle="Normal"
FontSize="14"></Label>
<TextBox BorderThickness="1"
FontWeight="Normal"
IsReadOnly="True"
Height="44"
Width="878"
TextWrapping="Wrap"
AcceptsReturn="True"
HorizontalAlignment="left"
Margin="0,0,0,0"
Name="txtShoreComment"
VerticalAlignment="Center" />
</StackPanel>
</Grid>
</Grid>

Categories

Resources