wpf mouse hover grid row first element - wpf

Is it possible to make when i hover over grid (template for items control) to change font color for first and last column in a row (this specific row which i am hovering)
What i want is "RowNumbering" object to change font color when we hover his "parent" row. To sort of highlite that row text.
Imagine it as a table:
where o is just a seat, and numbers are row numbers, when i hover over "o" i would like to change row number font color. I hope it's clear what i try, i did strip xaml to a minimum. Also would love to have this done over xaml if possible instead over code. Example bellow when i hover over "o" in second row.
1 | o | o | o | o | 1
2 | o | o | o | o | 2
3 | o | o | o | o | 3
<ItemsControl ItemsSource="{Binding Seats}" Name="SeatsItems">
<ItemsControl.RenderTransform>
<TranslateTransform X="0" Y="0" />
</ItemsControl.RenderTransform>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Name="ParentGrid" local:GridHelpers.RowCount="{Binding RowCount}"
local:GridHelpers.ColumnCount="{Binding ColumnCount}"
ShowGridLines="False" Background="#1C222E"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Grid.Row" Value="{Binding RowEx}" />
<Setter Property="Grid.RowSpan" Value="2" />
<Setter Property="Grid.Column" Value="{Binding ColumnEx}" />
<Setter Property="Grid.ColumnSpan" Value="{Binding ColSpan}" />
<Style.Triggers>
<!--
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Width" Value="60"/>
</Trigger>
-->
</Style.Triggers>
<Style.Resources>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="Available">
<Setter Property="Stroke" Value="#5D606D" />
<Setter Property="Fill" Value="#5D606D" />
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:Seat}">
<Canvas Name="Canv" Width="30" Height="30" Margin="4" Background="Transparent"
Tag="{Binding ID}">
<Rectangle Name="RecTop" Canvas.Top="4" Canvas.Left="1" Width="28"
Height="18" RadiusX="2" RadiusY="2" />
<Rectangle Name="RecBot" Canvas.Top="23" Canvas.Left="1" Width="28"
Height="7" RadiusX="2" RadiusY="2" />
<!-- <TextBlock Text="{Binding Path=Column}" TextWrapping="Wrap"
TextAlignment="Center" VerticalAlignment="Center" /> -->
</Canvas>
</DataTemplate>
<DataTemplate DataType="{x:Type local:RowNumbering}">
<Canvas Width="30" Height="30" Margin="4" Background="Transparent">
<TextBlock Text="{Binding Path=Text}" Foreground="#5D606D"
TextWrapping="Wrap" TextAlignment="Center"
VerticalAlignment="Center" Width="30" Height="20"
Margin="0,5" />
</Canvas>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Screen}">
<Canvas Height="5" Margin="0,0,0,33" Background="#EA1C47" ClipToBounds="False">
</Canvas>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>

I think you're using the wrong control type. WPF layout controls like Grid etc are useful when you want WPF to handle the layout of controls for you. In your case, however, the layout is already implicit in your data structures by virtue of the RowEx/ColumnEx properties. What you're trying to do is shoe-horn complex layout requirements into a layout control that's not really designed for it. You've already run into problems with this before, which has necessitated the use of that GridHelper. It's probably not going to get any better.
I write airline check-in systems for a living and find myself implementing systems very similar to what you're doing all the time. Experience has taught me that in cases like this, you're usually better off using a Canvas. It does require you to add much of the functionality that existing controls give you for free (e.g. row-specific behavior, which is something DataSet is better at handling), but it will give you complete flexibility over your layout and behaviors, and will also be much easier to unit-test.
To answer your question though, you could create a new class called Row with a transparent background that spans all of your columns. Bind that control's MouseEnter/MouseLeave events to update a local property in Row, and in those properties setters have them set/clear a highlight flag in the two RowNumbering instances that appear in that row. Alternatively each instance of RowNumbering could contain a property that points to its corresponding Row instance, and you could set a DataTrigger to trigger on that instead.

Related

In multiple Y axis graph, the axis shift issue in wpf

I have chart control,depends upon the selection i have to plot a graph,here is screen shot
First case i have selected, 2 inputs and second case given 1 input. as above images it shifts axis.If i refresh it will be the proper position.
<chartingToolkit:Chart Name="lineChart" BorderThickness="0" Padding="0"
Grid.IsSharedSizeScope="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<chartingToolkit:Chart.LegendStyle>
<Style TargetType="Control">
<Setter Property="Template" Value="{x:Null}"/>
</Style>
</chartingToolkit:Chart.LegendStyle>
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="X" Minimum="0" Maximum="{Binding MaxX}" Title="Time (Minutes)" />
</chartingToolkit:Chart.Axes>
<chartingToolkit:LineSeries Title="Oxygen" DependentValuePath="Value" IndependentValuePath="Key" Visibility="{Binding O2.GraphVisibility}"
ItemsSource="{Binding O2.TGraph,UpdateSourceTrigger=PropertyChanged}" IsSelectionEnabled="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Padding="0" >
<chartingToolkit:LineSeries.DataPointStyle>
<Style TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="{StaticResource graphO2}"/>
</Style>
</chartingToolkit:LineSeries.DataPointStyle>
<chartingToolkit:LineSeries.DependentRangeAxis>
<chartingToolkit:LinearAxis Title="{Binding O2.YTitle}" Foreground="{StaticResource graphO2}" Visibility="{Binding O2.YVisibility}" Maximum="{Binding O2.MaxY}" Orientation="Y" Location="{Binding O2.YLocation}" />
</chartingToolkit:LineSeries.DependentRangeAxis>
</chartingToolkit:LineSeries>
</chartingToolkit:Chart>
Using WPF Toolkit Data Visualization for graph.Please help me solve this issue.Coding side using MVVM architecuture.
It seems that chart doesn't refreshe in proper way, when you change input or modify dependency properties.
At least in LightningChart Visualization component, you can disable chart rendering - modify properties - continue rendering. You can easily prevent such bugs.
Try that and see the result. It has free demoapp with examples and available code. Can help you.

Displaying an alternative text when no image has been assigned yet

I have an image control on which the user can drag and drop pictures. When no image has been dropped in there and the control is empty, I'd like to show an alternative text such as "Drop a picture here" to better indicate what is expected from him/her.
I can't figure out how to use triggers with this, this shows nothing at all and I can no longer drop pictures on my image control:
<StackPanel Grid.Column="1" Grid.Row="2" FlowDirection="LeftToRight" Orientation="Horizontal" Margin="0px 4px">
<StackPanel.Resources>
<DataTemplate x:Key="tmpTemplate">
<Border BorderThickness="2" BorderBrush="#FF969DFF" CornerRadius="2" VerticalAlignment="Top">
<DockPanel>
<Image Name="imgSelectedViewImage" Source="{Binding Image}" MinWidth="32" MinHeight="32" MaxWidth="48" MaxHeight="48"
HorizontalAlignment="Left" Stretch="None"
IsEnabled="{Binding EditMode}" Margin="2px"/>
<Label Content="Drag here" Name="AltText" Visibility="Collapsed"></Label>
</DockPanel>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Image}" Value="{x:Null}">
<Setter TargetName="AltText" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</StackPanel.Resources>
I can't tell you what you've done to break your previously working drag and drop functionality and all I can do is to suggest you undo your changes to remedy that. However, if you want to display something when a collection is empty, then there's an easy way to do that. Using the collection's Count property is no good because it won't update when items are added or removed.
You can simply add an int property next to your item collection for this, but you have to make sure that you notify the INotifyPropertyChanged interface for it also when the collection property changes:
public ObservableCollection<YourItem> YourItems
{
get { return yourItems; }
set
{
yourItems = value;
NotifyPropertyChanged("YourItems");
NotifyPropertyChanged("YourItemsCount");
}
}
public int YourItemsCount
{
get { return YourItems.Count; }
}
Then you can use it in a simple DataTrigger like this:
<Grid>
<!-- Put your normal content here -->
<TextBlock FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="Drop images here">
<TextBlock.Style>
<Style>
<Setter Property="TextBlock.Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding YourItemsCount}" Value="0">
<Setter Property="TextBlock.Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
I did it by setting the TargetNullValue and the FallbackValue to a static resource. See the code snippet below. You can of course set it to everything else you want.
<Image Stretch="Uniform"
Grid.Row="0"
Grid.Column="1"
MaxHeight="250"
MaxWidth="250"
Margin="10"
Source="{Binding Path=Character.Portrait, TargetNullValue={StaticResource FallbackImage}, FallbackValue={StaticResource FallbackImage}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cal:ActionMessage MethodName="ChangePicture">
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</image>
Another approach, which could be more to your liking, as it uses triggers could be this solution: Handling null when binding to an Image in XAML (look at the accepted answer). However in my opinion setting TargetNullValue and the FallbackValue is the best way to go.

ListBox item template depends on item values

In WPF, MVVC applicaiton I have quite normal listbox:
<ListBox ItemsSource="{Binding Friends}">
</ListBox>
Then each item of list uses following datatemplate:
<DataTemplate DataType="{x:Type model:Friend}">
<Border BorderThickness="1" BorderBrush="Gray" Padding="3" Name="border" Margin="3">
<StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
<TextBlock Name="DescriptionDTDataType" Text="{Binding Path=ConnectedUserID}" />
<TextBlock Name="StatusTitle" Margin="8,0,4,0">Status:</TextBlock>
<TextBlock Name="Status" Text="{Binding Path=Approved}" />
<Button Content="Approve" Command="{x:Static inf:Commands.ApproveUserConnection}" CommandParameter="{Binding}"></Button>
<Button Content="Disapprove" Command="{x:Static inf:Commands.DisapproveUserConnection}" CommandParameter="{Binding}"></Button>
</StackPanel>
</Border>
</DataTemplate>
The question is... I want to hide one of the buttons on the basic of Friend.Approved property. For example if Friend.Approved has value "approved" I want to hide button Approved and show only button Dissaprove. On the other hand if Friend.Approved has value "disapproved" then I want opposite. How to achieve this?
Thank you.
Beside creating a IValueConverter there is a pure XAML solution using DataTriggers
Just add this to your DataTemplate:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Approved}" Value="approved" >
<Setter TargetName="Approve" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding Approved}" Value="disapproved" >
<Setter TargetName="Disapprove" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
And name your buttons:
<Button Name="Approve" Content="Approve" ...></Button>
<Button Name="Disapprove" Content="Disapprove" ...></Button>
However if you want to reuse this hiding logic in multiple places in multiple DataTemplates its better to write the Approved text to Visibility converter.
Bind the Buttons Visibility property to Approved and use a value converter to convert Approved to a Visibility value.

Binding the background colour of a control using a trigger in WPF/XAML

Okay, first off I have no experience of WPF whatsoever so please bear with me and apologies if my terminology is a little wayward... ;)
The following code snippet is part of a WPF application that I have inherited. The trigger governs whether mandatory fields on a particular form are highlighted or not. The code works but the highlighting seems to apply to the control and the border (??) which contains it.
<ItemsControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="clr-namespace:Caliburn.PresentationFramework.ApplicationModel;assembly=Caliburn.PresentationFramework"
x:Class="company.product.Jobs.JobParametersEditor"
IsTabStop="False">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel MinHeight="30">
<TextBlock Text="{Binding DisplayName, Mode=OneWay}"
DockPanel.Dock="Left"
VerticalAlignment="Center"
MinWidth="120"
Margin="6,0" />
<Border>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background"
Value="{x:Null}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsValid}"
Value="False">
<Setter Property="Background"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentControl cal:View.Model="{Binding ValueEditor}"
ToolTip="{Binding ToolTip}"
IsTabStop="False"
MinHeight="19"
VerticalAlignment="Center"
HorizontalAlignment="Stretch" />
</Border>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The result is a bit clunky so I would like to restrict the highlighting to the control only but I can't figure out how to do it. I've tried moving the trigger so that it applies to the ContentControl instead of the Border but that didn't work and fiddling about with border margins, padding and thickness hasn't had any effect either.
Could anybody enlighten me as to how to accomplish this?

Share column width between Grids in items of an ItemsControl

I'm writing a control to display and edit objects in a form. The control (FormDataView) is an ItemsControl where each item is a FormField control made of a Grid, with the field name in the left column and the editor (e.g. TextBox) in the right column. In order to align the editors, I want the first column in each Grid to share the same width.
So I tried to use IsSharedSizeScope and SharedSizeGroup, but it doesn't work, the first column has a different width in each FormField.
Here are the styles for these controls:
<Style TargetType="{x:Type ctl:FormDataView}" BasedOn="{StaticResource ResourceKey={x:Type ItemsControl}}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"
Grid.IsSharedSizeScope="True"
IsItemsHost="True" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ctl:FormField}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctl:FormField}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="headerColumn" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
Content="{TemplateBinding Header}"
Margin="3"
TextElement.FontWeight="Bold" />
<ContentPresenter Grid.Column="1"
Name="PART_Display"
ContentTemplate="{TemplateBinding DisplayTemplate}"
Margin="2"/>
<ContentPresenter Grid.Column="1"
Name="PART_Editor"
ContentTemplate="{TemplateBinding EditorTemplate}"
Margin="2"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsInEditMode, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctl:FormDataView}}}"
Value="True">
<Setter TargetName="PART_Display" Property="Visibility" Value="Collapsed" />
<Setter TargetName="PART_Editor" Property="Visibility" Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Notice how Grid.IsSharedSizeScope is set in the ItemsPanel of FormDataView, while SharedSizeGroup is set in the template of FormField. This correctly expresses what I want to do: each FormField should use the same width for the first column. However, according to the documentation for the SharedSizeGroup property, this scenario is not supported:
Grid size-sharing does not work if you set IsSharedSizeScope to true
within a resource template and you define SharedSizeGroup as outside
that template.
OK, so I can understand why it doesn't work... but I don't know how to work around this limitation.
Any idea?
N.B.: I don't want to assign a fixed width to the first column of course...
Sadly I have no access to my Visual Studio Enviroment so I couldnt check the following tips...
Assign Grid.IsSharedSizeScope="True" to FormDataView itself and not to the ItemsPanel. Do you really need StackPanel as the items panel? cant you live without that?
See if the above change works first...
if not then revamp your item level code and assign SharedSizeGroup="headerColumn" in your item data template of your FormDataView and not in the ControlTemplate of individual FormField.
Let me know if this helps....

Resources