<Grid>
<Grid x:Name="thumbGrid" ShowGridLines="True" ClipToBounds="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=ThumbSelectorLeftMargin, Mode=TwoWay}"/>
<ColumnDefinition Width="{Binding Path=ThumbWidthSelector, Mode=TwoWay}"/>
<ColumnDefinition Width="{Binding Path=ThumbSelectorRightMargin, Mode=TwoWay}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding Path=ThumbSelectorTopMargin, Mode=TwoWay}" />
<RowDefinition Height="{Binding Path=ThumbHeightSelector, Mode=TwoWay}"/>
<RowDefinition Height="{Binding Path=ThumbSelectorBottomMargin, Mode=TwoWay}"/>
</Grid.RowDefinitions>
<GridSplitter Grid.Column="0" Grid.RowSpan="3" HorizontalAlignment="Right" BorderBrush="Transparent"
BorderThickness="2" ShowsPreview="True" DragCompleted="ThumbLeftGridSplitterDragCompleted" />
<GridSplitter Grid.Column="2" Grid.RowSpan="3" HorizontalAlignment="Left" BorderBrush="Transparent"
BorderThickness="2" ShowsPreview="True" DragCompleted="ThumbRightGridSplitterDragCompleted" />
<Grid x:Name="thumbImgGrid" MouseDown="thumbImgGrid_MouseDown" MouseMove="thumbImgGrid_MouseMove" MouseUp="thumbImgGrid_MouseUp" Grid.Row="1" Grid.Column="1">
<Border x:Name="thumbBorder">
<Image Stretch="Fill"/>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ThumbBackgroundEntity.FillType}" Value="Color">
<Setter Property="Background" Value="{Binding Path=ThumbBackgroundEntity.BackgroundColor , Mode=TwoWay}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ThumbBackgroundEntity.FillType}" Value="NoFill">
<Setter Property="Background" Value="{Binding Path=ThumbBackgroundEntity.BackgroundColor , Mode=TwoWay}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Border Opacity="{Binding Path=ThumbBackgroundEntity.Opacity , Mode=TwoWay}">
<Image x:Name="thumbImage" Source="{Binding Path=ThumbBackgroundEntity.BackgroundImageFullPath , Mode=TwoWay, Converter={StaticResource StringToImgConverter}}"
RenderTransformOrigin="0.5, 0.5" Stretch="Fill">
<Image.LayoutTransform>
<RotateTransform Angle="{Binding Path=ThumbBackgroundEntity.ImageAngle , Mode=TwoWay}"/>
</Image.LayoutTransform>
</Image>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ThumbBackgroundEntity.FillType}" Value="Color">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ThumbBackgroundEntity.FillType}" Value="NoFill">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Grid>
<GridSplitter Grid.Row="0" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" BorderBrush="Transparent" BorderThickness="2" ShowsPreview="True"/>
<GridSplitter Grid.Row="2" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Top" BorderBrush="Transparent" BorderThickness="2" ShowsPreview="True" />
</Grid>
</Grid>
I want to move thumbImgGrid inside grid keeping height and width constant(maintain image aspect ratio)
I did following way but i could not maintain the height and width same on move.
On mouse down i calculated top left value of thumbImgGrid
private void thumbImgGrid_MouseDown(object sender, MouseButtonEventArgs e)
{
startTopLeft = thumbImgGrid.TranslatePoint(new Point(0, 0), trackGrid);
startRightBottom = new Point(startTopLeft.X + thumbImgGrid.ActualWidth, startTopLeft.Y + thumbImgGrid.ActualHeight);
thumbImgGrid.CaptureMouse();
}
Mouse move function,here i get the current thumbGrid position and get the difference of points with old and new position and difference is added or subtracted in old value.
private void thumbImgGrid_MouseMove(object sender, MouseEventArgs e)
{
if (thumbImgGrid.IsMouseCaptured)
{
Vector offset = Point.Subtract(e.GetPosition(thumbGrid), startTopLeft);
double newLeft = startTopLeft.X + offset.X;
double NewTop = startTopLeft.Y + offset.Y;
Point newRightBottom = new Point(newLeft + thumbImgGrid.ActualWidth, newLeft+ thumbImgGrid.ActualHeight);
//thumbImgGrid.Margin = new Thickness(newLeft, NewTop, newRightBottom.X, newRightBottom.Y);
_DataSource.ThumbSelectorLeftMargin = new GridLength(newLeft, GridUnitType.Star);
//_DataSource.ThumbWidthSelector = new GridLength(thumbImgGrid.ActualWidth, GridUnitType.Star);
//_DataSource.ThumbSelectorRightMargin = new GridLength(newLeft + thumbImgGrid.ActualWidth, GridUnitType.Star);
_DataSource.ThumbSelectorTopMargin = new GridLength(NewTop, GridUnitType.Star);
//_DataSource.ThumbHeightSelector = new GridLength(thumbImgGrid.ActualHeight, GridUnitType.Star);
// _DataSource.ThumbSelectorBottomMargin = new GridLength(newLeft + thumbImgGrid.ActualHeight, GridUnitType.Star);
_DataSource.UpdateThumbDimnsionLayout();
}
}
Mouse Up Function
private void thumbImgGrid_MouseUp(object sender, MouseButtonEventArgs e)
{
thumbImgGrid.ReleaseMouseCapture();
}
I am unable to maintain the height width constant on mouse move.
Thanks in advance.
Related
I am trying to do a tool for rectangle drawing and moving by ListBox in WPF. I use MouseLeftButtonDownOnRectangle to select rectangle, MouseMoveOnRectangle to drag rectangle, and MouseLeftButtonUpOnRectangle to drop rectangle. MouseLeftButtonDownOnRectangle and MouseMoveOnRectangle work ok, but MouseLeftButtonUpOnRectangle does not fire after MouseMoveOnRectangle. I have tried preview-event and non-preview-event, both of them do not work.
XAML
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
<Style TargetType="ListBox" x:Key="ShapesListBoxStyle">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
</Style>
<Style TargetType="ListBoxItem" x:Key="ShapesItemStyle">
<Setter Property="Canvas.Left" Value="{Binding Rectangle.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Rectangle.Y}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Rectangle
x:Name="LabelShapeFill"
HorizontalAlignment="Left"
Width="{Binding Rectangle.Width}"
Height="{Binding Rectangle.Height}"
Fill="{Binding Hexadecimal}"
Stroke="{Binding Hexadecimal}"
Opacity="0.1">
</Rectangle>
<Rectangle
x:Name="LabelShapeBorder"
HorizontalAlignment="Left"
Width="{Binding Rectangle.Width}"
Height="{Binding Rectangle.Height}"
Stroke="{Binding Hexadecimal}"
StrokeThickness="1">
</Rectangle>
<Grid Height="20" Margin="0 0 0 -20" VerticalAlignment="Bottom" Visibility="Collapsed" x:Name="LabelShapeControlPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45"/>
</Grid.ColumnDefinitions>
<Button Content="Delete" Width="45" Height="20" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Viewbox>
<Grid>
<b:Interaction.Triggers>
<b:EventTrigger EventName="PreviewMouseLeftButtonDown">
<b:InvokeCommandAction Command="{Binding PreviewMouseLeftButtonDownOnWindow}"/>
</b:EventTrigger>
<b:EventTrigger EventName="MouseLeftButtonDown">
<b:InvokeCommandAction Command="{Binding MouseLeftButtonDownOnWindow}"/>
</b:EventTrigger>
<b:EventTrigger EventName="PreviewMouseLeftButtonUp">
<b:InvokeCommandAction Command="{Binding PreviewMouseLeftButtonUpOnWindow}"/>
</b:EventTrigger>
<b:EventTrigger EventName="MouseLeftButtonUp">
<b:InvokeCommandAction Command="{Binding MouseLeftButtonUpOnWindow}"/>
</b:EventTrigger>
<b:EventTrigger EventName="MouseMove">
<b:InvokeCommandAction Command="{Binding MouseMoveOnWindow}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
<b:Interaction.Behaviors>
<mb:MouseBehaviour MouseX="{Binding MouseX, Mode=OneWayToSource}" MouseY="{Binding MouseY, Mode=OneWayToSource}" />
</b:Interaction.Behaviors>
<Image x:Name="Img" Source="{Binding CurrentPhoto}" RenderOptions.BitmapScalingMode="Unspecified" Stretch="Uniform"/>
<ListBox
ItemsSource="{Binding Shapes}"
Width="{Binding ActualWidth, ElementName=Img}"
Height="{Binding ActualHeight, ElementName=Img}"
VerticalAlignment="Top"
HorizontalAlignment="Left"
SelectionMode="Extended"
Style="{StaticResource ShapesListBoxStyle}"
ItemContainerStyle="{StaticResource ShapesItemStyle}"
SelectedIndex="{Binding SelectedShapeIndex}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="PreviewMouseLeftButtonDown">
<b:InvokeCommandAction Command="{Binding PreviewMouseLeftButtonDownOnRectangle}"/>
</b:EventTrigger>
<b:EventTrigger EventName="MouseLeftButtonDown">
<b:InvokeCommandAction Command="{Binding MouseLeftButtonDownOnRectangle}"/>
</b:EventTrigger>
<b:EventTrigger EventName="PreviewMouseLeftButtonUp">
<b:InvokeCommandAction Command="{Binding PreviewMouseLeftButtonUpOnRectangle}"/>
</b:EventTrigger>
<b:EventTrigger EventName="MouseLeftButtonUp">
<b:InvokeCommandAction Command="{Binding MouseLeftButtonUpOnRectangle}"/>
</b:EventTrigger>
<b:EventTrigger EventName="PreviewMouseMove">
<b:InvokeCommandAction Command="{Binding PreviewMouseMoveOnRectangle}"/>
</b:EventTrigger>
<b:EventTrigger EventName="MouseMove">
<b:InvokeCommandAction Command="{Binding MouseMoveOnRectangle}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</ListBox>
<Canvas
Width="{Binding ActualWidth, ElementName=Img}"
Height="{Binding ActualHeight, ElementName=Img}">
<Border
Canvas.Left="{Binding DrawStartX}"
Canvas.Top="{Binding DrawStartY}"
x:Name="dragSelectionBorder"
Width="{Binding DrawWidth}"
Height="{Binding DrawHeight}"
BorderBrush="{Binding Hexadecimal}"
BorderThickness="2"
Background="LightBlue"
Opacity="0.5"/>
</Canvas>
</Grid>
</Viewbox>
I use the following code to get mouse position. I suspect this code cause the problem. But I have no idea how to fix it.
MouseBehaviour.cs
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Core
{
public class MouseBehaviour : Behavior<Grid>
{
public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
"MouseY", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
"MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
public double MouseY
{
get { return (double)GetValue(MouseYProperty); }
set { SetValue(MouseYProperty, value); }
}
public double MouseX
{
get { return (double)GetValue(MouseXProperty); }
set { SetValue(MouseXProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
}
private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var pos = mouseEventArgs.GetPosition(AssociatedObject);
MouseX = pos.X;
MouseY = pos.Y;
}
protected override void OnDetaching()
{
AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
}
}
}
Screenshot
My code:
<DataGrid HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Hidden" BorderBrush="#83D744" IsSynchronizedWithCurrentItem="False" VerticalGridLinesBrush="Transparent" Grid.Column="0" RowHeaderWidth="0" CanUserAddRows="False" AutoGenerateColumns="False" x:Name="datagrid1" Margin="10,150,8,50" Background="Transparent" RowBackground="#FF494949" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" ItemsSource="{Binding}">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#83D744"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="50"/>
</Style>
<Style x:Key="TextInCellCenter" TargetType="{x:Type TextBlock}" >
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="RightAligElementStyle">
<Setter Property="TextAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="LeftAligElementStyle">
<Setter Property="TextAlignment" Value="Left"/>
</Style>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent"/>
</DataGrid.Resources>
<DataGrid.Columns >
<DataGridTextColumn Binding="{Binding ProductName}" ElementStyle="{StaticResource LeftAligElementStyle}" Header="NAZIV ARTIKLA" MinWidth="350" Foreground="White" FontSize="20" FontFamily="Verdana" />
<DataGridTextColumn Binding="{Binding Quantity}" ElementStyle="{StaticResource TextInCellCenter}" Header="KOLIČINA" MinWidth="200" Foreground="White" FontSize="20" FontFamily="Verdana" />
</DataGrid.Columns>
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Background="Black" Opacity="0.7">
<Expander.Header >
<DockPanel Height="50" Margin="0,0,0,0" Name="dockPanel" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=ActualWidth}">
<Button Name="btnFinishOrder" Content="Finish Order" Margin="0,0,55,5" DockPanel.Dock="Right" Click="btnFinishOrder_Click" FontSize="12" BorderThickness="1.5" HorizontalAlignment="Left" VerticalAlignment="Bottom" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="#83D744" Background="Transparent" BorderBrush="#83D744" Width="130" Height="40">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush= "{TemplateBinding BorderBrush}"
Background= "{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Button Name="btnTakeIt" Click="btnTakeIt_Click" Content="Take it" Margin="0,0,20,5" DockPanel.Dock="Right" FontSize="12" BorderThickness="1.5" HorizontalAlignment="Left" VerticalAlignment="Bottom" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="#83D744" Background="Transparent" BorderBrush="#83D744" Width="130" Height="40">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock FontWeight="Normal" FontFamily="Verdana" FontSize="20" Height="25" Foreground="#83D744" Text="{Binding Path=Name,StringFormat= Number of Order:# {0}}" />
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
There you can see guys, when I click on button Click="btnTakeIt_Click" I programaticaly change buttons text to "Order in progress." and I update field in my database IsInProgres to 1 - true, code is here:
private void btnTakeIt_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
CollectionViewGroup group = b.DataContext as CollectionViewGroup;
var x = group.Name;
int orderNumber = Convert.ToInt32(x);
b.BorderBrush = null;
b.Content = "Order is in progress";
b.FontSize = 12;
OrdersController.SetOrderInProgressByID(orderNumber);
}
But what is happening, because I'm refreshing my grid every 20 seconds my button content is becoming again like it's on default "Take it!" because that's whats written in XAML.
Like this:
This is my code behind (refresh every few seconds):
public MainWindow()
{
try
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
this.WindowState = WindowState.Maximized;
var ordersList = OrdersController.localOrders();
collectionViewSource.Source = ordersList;
collectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("NumberOfOrder"));
DataContext = collectionViewSource;
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(20);
timer.Tick += timer_Tick;
timer.Start();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void timer_Tick(object sender, EventArgs e)
{
var ordersList = OrdersController.localOrders();
collectionViewSource.Source = null;
collectionViewSource.Source = ordersList;
DataContext = collectionViewSource;
datagrid1.ScrollIntoView(datagrid1.Items[datagrid1.Items.Count - 1]);
}
}
So my question is could I somehow loop my localOrders and check if NumberOfOrder has IsInProgress = 1 and simply set this:
btnTakeIt.Content="Order in progress.."
So everytime my grid refresh I can loop my orders, and check is order InProgress and after that I can set button btnTakeIt content to "Order in progress.."
Or if there is any other way, I am opened to try it!
P.S I tried allready but my btnTakeIt is not accessible in code behind :(
EDIT:
void timer_Tick(object sender, EventArgs e)
{
Button MyButton = FindChild<Button>(datagrid1, "btnTakeIt");
var ordersList = OrdersController.localOrders();
collectionViewSource.Source = null;
collectionViewSource.Source = ordersList;
foreach (var item in ordersList)
{
if (item.IsInProgress== true)
{
MyButton.Content = "Order is in progress";
}
}
DataContext = collectionViewSource;
}
Can I do it like this? I checked debuger and it is entering inside of if statement and when I look at breakpoint it acctualy changes content but on grid I can not see anything changed :(
EDIT:
I have to mention that my class Product is contained in my OrdersController :)
#Ayuman
what do you think about this:
<Button Name="btnTakeIt" DataContext="{Binding Items[0]}" Content="{Binding Status}"Click="btnTakeIt_Click" Content="Take it" Margin="0,0,20,5" DockPanel.Dock="Right" FontSize="12" BorderThickness="1.5" HorizontalAlignment="Left" VerticalAlignment="Bottom" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="#83D744" Background="Transparent" BorderBrush="#83D744" Width="130" Height="40">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
code behind:
public static List<LocalOrders> localOrders()
{
var results = DataServices.POS.proc_GetAllOrders().ToList();
List<LocalOrders> localOrdersList = new List<LocalOrders>();
foreach (var item in results)
{
LocalOrders lokal = new LocalOrders();
if (item.IsInProgress)
{
localo.Pihvacena = true;
localo.Status = "IN PROCESS";
}
else
{
lokalne.Status = "IT IS NOT YET IN PROCESS";
}
lokal.User = item.User;
lokal.Quantity = Convert.ToInt32(item.Quantity);
lokal.Title = item.Title;
lokal.NumberOfOrder = item.NumberOfOrder;
localOrdersList.Add(lokal);
}
return localOrdersList;
}
So I can programaticaly check for status of order and set content of button like that.. is it good solution maybe?
Please refer below code. I tried to make it work. Hope this works for you as well
<DataGrid HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Hidden" BorderBrush="#83D744" IsSynchronizedWithCurrentItem="False" VerticalGridLinesBrush="Transparent" Grid.Column="0" RowHeaderWidth="0" CanUserAddRows="False" AutoGenerateColumns="False" x:Name="datagrid1" Margin="10,150,8,50" Background="Transparent" RowBackground="#FF494949" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" ItemsSource="{Binding}">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#83D744"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="50"/>
</Style>
<Style x:Key="TextInCellCenter" TargetType="{x:Type TextBlock}" >
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="RightAligElementStyle">
<Setter Property="TextAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="LeftAligElementStyle">
<Setter Property="TextAlignment" Value="Left"/>
</Style>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent"/>
</DataGrid.Resources>
<DataGrid.Columns >
<DataGridTextColumn Binding="{Binding ProductName}" ElementStyle="{StaticResource LeftAligElementStyle}" Header="NAZIV ARTIKLA" MinWidth="350" Foreground="White" FontSize="20" FontFamily="Verdana" />
<DataGridTextColumn Binding="{Binding Quantity}" ElementStyle="{StaticResource TextInCellCenter}" Header="KOLIČINA" MinWidth="200" Foreground="White" FontSize="20" FontFamily="Verdana" />
</DataGrid.Columns>
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Background="Black" Opacity="0.7">
<Expander.Header >
<DockPanel Height="50" Margin="0,0,0,0" Name="dockPanel" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=ActualWidth}">
<Button Name="btnFinishOrder" DataContext="{Binding Items[0]}" Content="{Binding ButtonCaption}" Margin="0,0,55,5" DockPanel.Dock="Right" Click="BtnFinishOrder_OnClick" FontSize="12" BorderThickness="1.5" HorizontalAlignment="Left" VerticalAlignment="Bottom" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="#83D744" Background="Transparent" BorderBrush="#83D744" Width="130" Height="40">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush= "{TemplateBinding BorderBrush}"
Background= "{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Button Name="btnTakeIt" Click="BtnTakeIt_OnClick" DataContext="{Binding Items[0]}" Content="{Binding ButtonCaption}" Margin="0,0,20,5" DockPanel.Dock="Right" FontSize="12" BorderThickness="1.5" HorizontalAlignment="Left" VerticalAlignment="Bottom" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="#83D744" Background="Transparent" BorderBrush="#83D744" Width="130" Height="40">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock FontWeight="Normal" FontFamily="Verdana" FontSize="20" Height="25" Foreground="#83D744" Text="{Binding Items[0].ProductName}" />
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
public partial class MainWindow : Window
{
private ICollectionView view;
private ObservableCollection<Product> ordersList;
public MainWindow()
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
this.WindowState = WindowState.Maximized;
ordersList = new ObservableCollection<Product>()
{
new Product()
{
ProductName = "Prodct",
Quantity = 1,
NumberOfOrder = 100,
IsInProgress = true,
ButtonCaption = "Take it"
},
new Product()
{
ProductName = "Prodct1",
Quantity = 2,
NumberOfOrder = 1000,
ButtonCaption = "Take it"
},
new Product()
{
ProductName = "Prodct2",
Quantity = 3,
NumberOfOrder = 10000,
ButtonCaption = "Take it"
},
new Product()
{
ProductName = "Prodct3",
Quantity = 4,
NumberOfOrder = 100000,
ButtonCaption = "Take it"
},
};
view = CollectionViewSource.GetDefaultView(ordersList);
view.GroupDescriptions.Add(new PropertyGroupDescription("NumberOfOrder"));
DataContext = view;
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(20);
timer.Tick += Timer_Tick; ;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
foreach (var item in ordersList)
{
if (item.IsInProgress)
{
item.ButtonCaption = "Order is Still in progress";
}
}
}
private void BtnFinishOrder_OnClick(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
private void BtnTakeIt_OnClick(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
Product prod = b.DataContext as Product;
b.BorderBrush = null;
prod.ButtonCaption = "Order is in progress";
b.FontSize = 12;
}
}
class Product:INotifyPropertyChanged
{
private string productName;
public string ProductName
{
get { return productName ; }
set
{
productName = value ;
OnPropertyChanged("ProductName");
}
}
private int quantity;
public int Quantity
{
get { return quantity; }
set
{
quantity = value;
OnPropertyChanged("Quantity");
}
}
public int NumberOfOrder { get; set; }
public bool IsInProgress { get; set; }
private string buttonCaption;
public string ButtonCaption
{
get { return buttonCaption; }
set
{
buttonCaption = value;
OnPropertyChanged("ButtonCaption");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I want to show a close button on top of a control only when mouse is over the control, and hide otherwise. Of course, the button should stay when mouse moves from the control to the button. So, I can't simply use IsMouseOver trigger or MouseEnter on the underlining control.
I tried to use a trigger on Grid, but Grid doesn't have IsMouseOver property:
<Grid>
<!-- other controls -->
<Button x:Name="closeButton" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5" Margin="0 -5 -5 0" Padding="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" VerticalAlignment="Top" Background="Transparent" HorizontalAlignment="Right" Command="{Binding HideControlCommand}" ToolTip="Hide">
<Border x:Name="circleBorder" CornerRadius="{Binding ActualHeight, ElementName=circleBorder}" Width="{Binding ActualHeight, ElementName=circleBorder}" BorderBrush="Black" Background="LightGray" Padding="3" BorderThickness="1">
<Grid Name="parent" Width="10" Height="10">
<Line X1="0" Y1="0" X2="{Binding ElementName='parent', Path='ActualWidth'}" Y2="{Binding ElementName='parent', Path='ActualHeight'}" Stroke="Black" StrokeThickness="2" />
<Line X1="0" Y1="{Binding ElementName='parent', Path='ActualHeight'}" X2="{Binding ElementName='parent', Path='ActualWidth'}" Y2="0" Stroke="Black" StrokeThickness="2" />
</Grid>
</Border>
</Button>
<Grid.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Visibility" Value="Visible" TargetName="closeButton"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Visibility" Value="Collapse" TargetName="closeButton"/>
</Trigger>
</Grid.Triggers>
</Grid>
This is very common in web app, but how to do it in wpf?
You can use Datatriggers, i am using this one also for error strip on usercontrol.
Style for stackpanel show hide.
<Style x:Key="PanelStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsException}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding IsException}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
Stackpanel with close button where message(error/warning) will show ..
<StackPanel Margin="10" Style="{StaticResource PanelStyle}">
<StackPanel Orientation="Horizontal">
<StackPanel Margin="10" Background="Red" >
<TextBlock Text="{Binding LstError, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
NotifyOnSourceUpdated=True}" />
</StackPanel>
<Button Width="18" Height="18" Content="X" Command="{Binding CloseStrip}"
HorizontalAlignment="Right" Cursor="Hand" FontSize="12" FontWeight="Bold"
Foreground="#FFEF0909" Padding="0" ToolTip="Close"></Button>
</StackPanel>
</StackPanel>
in viewmodel you have to create a Icomand type property for button.
public DelegateCommand CloseStrip { get; set; }
//this is contructor
public WriteOnStrip()
{
CloseStrip = new DelegateCommand(Close, CanClose);
}
private void Close()
{
LstError = "";
IsException = false;
}
private bool CanClose()
{
return true;
}
I would use css to do this. Just keep the opacity at 0 until you roll over it.
#test {
opacity: 0;
}
#test:hover {
opacity: 1;
}
Check out the js fiddle...
http://jsfiddle.net/qku6a/
I need to do something like that:
It's Listbox with custom DataTemplate for elements. (I drew green a whole one element of list.)
Now I have this:
If it's real - how to change my DataTemplate(or Listbox styles) to get first resul? (Somehow to set selected area)
DataTemplate
<DataTemplate x:Key="TrackDataTemplate">
<Grid Margin="0,-5,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding FirstPlatformName}" Grid.Row="0" Grid.Column="0"/>
<Path x:Name="Node"
Margin="10,0" Grid.Row="0" Grid.Column="1"
Data="M3.1999443,36.501999 L47.300057,36.501999 47.292366,36.517475 C43.192585,44.521747 34.86105,50 25.25,50 15.638952,50 7.3074172,44.521747 3.2076359,36.517475 z M25.25,0.5 C38.919049,0.49999976 50,11.580952 50,25.25 50,27.599367 49.672657,29.87228 49.061096,32.025615 L48.919384,32.501999 1.5806161,32.501999 1.438906,32.025615 C0.82734287,29.87228 0.5000003,27.599367 0.5,25.25 0.5000003,11.580952 11.580953,0.49999976 25.25,0.5 z"
Fill="{DynamicResource white75}" Stretch="Fill"
Width="17" Height="17"/>
<Rectangle x:Name="Connection" Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Center" VerticalAlignment="Top"
Fill="{DynamicResource white75}" Height="17" Width="4" Margin="10,2,10,0"/>
<TextBlock Grid.Row="1" Grid.Column="2" TextWrapping="Wrap"
Text="{Binding TsAndChannelNumber}"/>
</Grid>
</DataTemplate>
Listbox
<ListBox Grid.Column="1"
SelectedItem="{Binding SelectedTrackSegment}"
ItemsSource="{Binding SelectedTrack.Segments}"
ItemTemplate="{StaticResource TrackDataTemplate}"
Margin="30,20,30,0"/>
For complete control over the ListBoxItem you probably need to change the Template in ItemContainerStyle.
Heres a little test project to show what I mean.
NB Ive added 2 grids around your textblocks so that the Background Property can be changed using the Triggers.
Xaml
<ListBox x:Name="MyList">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Margin="0,-5,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="PlatformGrid">
<TextBlock Text="{Binding FirstPlatformName}" />
</Grid>
<Path x:Name="Node"
Margin="10,0" Grid.Row="0" Grid.Column="1"
Data="M3.1999443,36.501999 L47.300057,36.501999 47.292366,36.517475 C43.192585,44.521747 34.86105,50 25.25,50 15.638952,50 7.3074172,44.521747 3.2076359,36.517475 z M25.25,0.5 C38.919049,0.49999976 50,11.580952 50,25.25 50,27.599367 49.672657,29.87228 49.061096,32.025615 L48.919384,32.501999 1.5806161,32.501999 1.438906,32.025615 C0.82734287,29.87228 0.5000003,27.599367 0.5,25.25 0.5000003,11.580952 11.580953,0.49999976 25.25,0.5 z"
Fill="Blue" Stretch="Fill"
Width="17" Height="17"/>
<Rectangle x:Name="Connection" Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Center" VerticalAlignment="Top"
Fill="Blue" Height="17" Width="4" Margin="10,2,10,0"/>
<Grid x:Name="TSGrid" Grid.Row="1" Grid.Column="2">
<TextBlock TextWrapping="Wrap" Text="{Binding TsAndChannelNumber}"/>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="PlatformGrid" Value="Red"/>
<Setter Property="Background" TargetName="TSGrid" Value="Red"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
MainWindows.cs
public MainWindow()
{
InitializeComponent();
Loaded += (s, args) =>
{
this.DataContext = this;
MyList.ItemsSource = LoadSegments();
};
}
private static List<Segment> LoadSegments()
{
var segments = new List<Segment>
{
new Segment { FirstPlatformName = "FPName01", TsAndChannelNumber = "TSNumber0(ChannelNumber0" },
new Segment { FirstPlatformName = "FPName01", TsAndChannelNumber = "TSNumber0(ChannelNumber1" },
new Segment { FirstPlatformName = "FPName01", TsAndChannelNumber = "TSNumber0(ChannelNumber2" },
new Segment { FirstPlatformName = "FPName01", TsAndChannelNumber = "TSNumber0(ChannelNumber3" },
new Segment { FirstPlatformName = "FPName01", TsAndChannelNumber = "TSNumber0(ChannelNumber4" }
};
return segments;
}
Segment.cs
public class Segment
{
public string FirstPlatformName { get; set; }
public string TsAndChannelNumber { get; set; }
}
You will ideally need to 'Edit a copy' of the ItemContainerStyle template in Blend so you get access to all the standard behaviours and then edit the Trigger IsSelected as above
Hope that helps
But I suggest to use two ListBox and use IsSynchronizedWithCurrentItem property to true. So when you make selection on one, it will select the same item on other automatically. And you can define your own data template for each listbox.
I have a datagrid in my form which has columns for each of Question Types.
I want that column to be split into two as i want to accept number of compulsory and number of optional questions for each of the question type in the subsequent columns.
I have achieved this in winforms, thanks to stackoverflow.com.
I am trying to achieve the same in WPF
Thanks in advance
I guess this is the DataGrid layout you want.... right?
.------.-----------------.--------.
| | ID Details | |
| Name |-----------------| Status |
| | ID | Passport | |
|------|------|----------|--------|
|X | 123 | E567868 | Present|
|Y | 236 | 7875678 | Absent |
'------'------'----------'--------'
WPF datagrid doesnt support this readily. But you can do some stretchy coding. The code like below can split the headers. You need to take caution that ...
When the split columns are reordered (DataGrid.ColumnReordered
event), all the sibling columns under their common parent header should be
moved, together. I am leaving that code to you.
Have some custom styles for DataGridHeaders
<Style TargetType="{x:Type Primitives:DataGridColumnHeader}"
x:Key="SplitHeaderStyle">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Primitives:DataGridColumnHeader}">
<DockPanel LastChildFill="True">
<Grid DockPanel.Dock="Bottom">
<Controls:DataGridHeaderBorder
SortDirection="{TemplateBinding SortDirection}"
IsHovered="{TemplateBinding IsMouseOver}"
IsPressed="{TemplateBinding IsPressed}"
IsClickable="{TemplateBinding CanUserSort}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding ="{TemplateBinding Padding}"
SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
SeparatorBrush="{TemplateBinding SeparatorBrush}">
<ContentPresenter
Content="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Content[0]}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="Center"/>
</Controls:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left"
Style="{StaticResource ColumnHeaderGripperStyle}"/>
<Thumb x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right"
Style="{StaticResource ColumnHeaderGripperStyle}"/>
</Grid>
<Grid DockPanel.Dock="Top">
<Controls:DataGridHeaderBorder
HorizontalAlignment="Stretch"
IsClickable="False"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding SeparatorBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding ="{TemplateBinding Padding}"
SeparatorVisibility="{TemplateBinding Tag}"
SeparatorBrush="{TemplateBinding SeparatorBrush}">
<ContentPresenter
Content="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Content[1]}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="-8,2,-10,2"/>
</Controls:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftSplitHeaderGripper"
HorizontalAlignment="Right"
Visibility="{TemplateBinding Tag}"
Style="{StaticResource ColumnHeaderGripperStyle}"/>
</Grid>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Primitives:DataGridColumnHeader}"
BasedOn="{StaticResource SplitHeaderStyle}"
x:Key="SplitHeaderLeftStyle">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Tag" Value="{x:Static Visibility.Visible}"/>
</Style>
<Style TargetType="{x:Type Primitives:DataGridColumnHeader}"
BasedOn="{StaticResource SplitHeaderStyle}"
x:Key="SplitHeaderRightStyle">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="Tag" Value="{x:Static Visibility.Collapsed}"/>
</Style>
Have columns arranged like this...
<Controls:DataGrid.Columns>
<Controls:DataGridTextColumn
Header="Name"
Binding="{Binding Name}"/>
<Controls:DataGridTextColumn
Binding="{Binding ID}"
HeaderStyle="{StaticResource SplitHeaderRightStyle}">
<Controls:DataGridTextColumn.Header>
<x:ArrayExtension Type="System:String">
<System:String>ID</System:String>
<System:String>ID De</System:String>
</x:ArrayExtension>
</Controls:DataGridTextColumn.Header>
</Controls:DataGridTextColumn>
<Controls:DataGridTextColumn
Binding="{Binding Passport}"
HeaderStyle="{StaticResource SplitHeaderLeftStyle}">
<Controls:DataGridTextColumn.Header>
<x:ArrayExtension Type="System:String">
<System:String>Passport</System:String>
<System:String>tails</System:String>
</x:ArrayExtension>
</Controls:DataGridTextColumn.Header>
</Controls:DataGridTextColumn>
<Controls:DataGridTextColumn
Header="Status"
Binding="{Binding Status}"/>
</Controls:DataGrid.Columns>
So basically you use the same default header layout of DataGrid but hack it in a way that two headers look like they are joined together.
C#
Name your DataGrid e.g. x:Name="MyDataGrid".
Keep all the styles in XAML in <DataGrid.Resources ..> tag. Make sure that they have x:Key set. e.g. x:Key="SplitHeaderLeftStyle" & x:Key="SplitHeaderRightStyle"
<DataGrid x:Name="MyDataGrid">
<DataGrid.Resources>
<Style
TargetType="{x:Type Primitives:DataGridColumnHeader}"
x:Key="SplitHeaderStyle" .../>
<Style x:Key="SplitHeaderLeftStyle"
BasedOn="{StaticResource SplitHeaderStyle}".../>
<Style x:Key="SplitHeaderRightStyle"
BasedOn="{StaticResource SplitHeaderStyle}" .../>
</DataGrid.Resources>
...
</DataGrid>
in your C# code when you add columns, set the styles by their Key.
var dgIDColumn
= new DataGridTextColumn()
{
Header = new string[] { "ID", "ID Det" },
Binding = new Binding() { Path = new PropertyPath("ID") },
HeaderStyle = MyDataGrid.FindResource("SplitHeaderRightStyle") as Style;
};
MyDataGrid.Columns.Add(dgIDColumn);
var dgPassportColumn
= new DataGridTextColumn()
{
Header = new string[] { "Passport", "ails" },
Binding = new Binding() { Path = new PropertyPath("Passport") },
HeaderStyle = MyDataGrid.FindResource("SplitHeaderLeftStyle") as Style;
};
MyDataGrid.Columns.Add(dgPassportColumn);
<DataGrid ItemsSource="{Binding PeopleList}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:Person}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="10"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Question1" Grid.ColumnSpan="2"/>
<TextBlock Text="Compulsory" Grid.Row="1"/>
<TextBlock Text="Optional Q" Grid.Row="1" Grid.Column="2"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:Person}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="65"/>
<ColumnDefinition/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Question.Col1}"/>
<TextBlock Text="{Binding Question.Col2}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
You can modify the Row/Column/ColumnSpan/RowSpan in DataTriggers of ItemsControl.ItemContainerStyle to your liking.
<ItemsControl ItemsSource="{Binding Path=Cells}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid
local:GridHelpers.ColumnCount="{Binding NumOfColumns}"
local:GridHelpers.AutoColumns="0,1"
local:GridHelpers.RowCount="{Binding NumOfRows}"
local:GridHelpers.AutoRows="0,1">
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Grid.Row" Value="{Binding Path=RowIndex}"/>
<Setter Property="Grid.Column" Value="{Binding Path=ColumnIndex}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CellType}" Value="BaseCell">
<Setter Property="ContentTemplate" Value="{StaticResource BaseCell}"/>
<Setter Property="Grid.ColumnSpan" Value="{Binding Path=ColumnSpan}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=CellType}" Value="CornerHeader">
<Setter Property="ContentTemplate" Value="{StaticResource CornerHeader}"/>
<Setter Property="Grid.RowSpan" Value="2"/>
<Setter Property="Grid.ColumnSpan" Value="2"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=CellType}" Value="PersonNameCell">
<Setter Property="ContentTemplate" Value="{StaticResource PersonNameCell}"/>
</DataTrigger>
...
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
I've added AutoColumns property to GridHelper class which is explained in this link
#region AutoColumns Property
/// <summary>
/// Makes the specified Column's Width equal to Auto.
/// Can set on multiple Columns
/// </summary>
public static readonly DependencyProperty AutoColumnsProperty =
DependencyProperty.RegisterAttached(
"AutoColumns", typeof(string), typeof(GridHelpers),
new PropertyMetadata(string.Empty, AutoColumnsChanged));
// Get
public static string GetAutoColumns(DependencyObject obj)
{
return (string)obj.GetValue(AutoColumnsProperty);
}
// Set
public static void SetAutoColumns(DependencyObject obj, string value)
{
obj.SetValue(AutoColumnsProperty, value);
}
// Change Event - Makes specified Column's Width equal to Auto
public static void AutoColumnsChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || string.IsNullOrEmpty(e.NewValue.ToString()))
return;
SetAutoColumns((Grid)obj);
}
private static void SetAutoColumns(Grid grid)
{
string[] autoColumns = GetAutoColumns(grid).Split(',');
for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
{
if (autoColumns.Contains(i.ToString()))
grid.ColumnDefinitions[i].Width = GridLength.Auto;
}
}
private static void SetAutoRows(Grid grid)
{
string[] autoRows = GetAutoRows(grid).Split(',');
for (int i = 0; i < grid.RowDefinitions.Count; i++)
{
if (autoRows.Contains(i.ToString()))
grid.RowDefinitions[i].Height = GridLength.Auto;
}
}
#endregion