Custom event trigger - c#

I have custom range slider which works fine but I would like to change the colour of the text boxes, here is my XAML:
<UserControl x:Class="Slider.RangeSlider"
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:Slider"
mc:Ignorable="d"
x:Name="root"
>
<UserControl.Resources>
<ControlTemplate x:Key="simpleSlider" TargetType="{x:Type Slider}">
<Border SnapsToDevicePixels="true"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle x:Name="PART_SelectionRange"/>
<Track x:Name="PART_Track" Grid.Row="1">
<Track.Thumb>
<Thumb x:Name="Thumb">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="#C0C0C0"
Stroke="Black"
StrokeThickness="1"
Width="10"
Height="18"
SnapsToDevicePixels="True"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
</Track>
</Grid>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderThickness="0,0,0,0"
BorderBrush="White"
VerticalAlignment="Center"
Height="1"
Margin="5,0,5,0"/>
<Rectangle Grid.Row="0" VerticalAlignment="Center" Fill="#FFF78A09" Height="5" MaxHeight="5" Margin="10,0,20,0"/>
<Slider x:Name="LowerSlider" Minimum="1" Grid.Row="1"
Maximum="12"
Value="{Binding LowerValue, ElementName=root}" IsSnapToTickEnabled="True" TickPlacement="Both"
Ticks="1,2,3,4,5,6,7,8,9,10,11,12" Template="{StaticResource simpleSlider}"
Margin="10,0,20,0"/>
<Slider x:Name="UpperSlider" Grid.Row="0" Thumb.DragCompleted="Thumb_Complete"
Minimum="1"
Maximum="12"
Value="{Binding UpperValue, ElementName=root}" IsSnapToTickEnabled="True" TickPlacement="Both"
Ticks="1,2,3,4,5,6,7,8,9 10,11,12" Template="{StaticResource simpleSlider}"
Margin="10,0,20,0"/>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBox Name="Month1" Text="Jan" Width="30" Margin="1.6,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
<TextBox Name="Month2" Text="Feb" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
<TextBox Name="Month3" Text="Mar" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
<TextBox Name="Month4" Text="Apr" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
<TextBox Name="Month5" Text="May" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
<TextBox Name="Month6" Text="Jun" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
<TextBox Name="Month7" Text="Jul" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
<TextBox Name="Month8" Text="Aug" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
<TextBox Name="Month9" Text="Sep" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
<TextBox Name="Month10" Text="Oct" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
<TextBox Name="Month11" Text="Nov" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
<TextBox Name="Month12" Text="Dec" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
</StackPanel>
</Grid>
Here is the C# code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Slider
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class RangeSlider : UserControl
{
public RangeSlider()
{
InitializeComponent();
}
public RoutedEventHandler Custom_Complete;
private void Thumb_Complete(object sender,RoutedEventArgs e)
{
if (Custom_Complete !=null)
{
Custom_Complete(this, new RoutedEventArgs());
}
}
#region Setting dependancies
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d));
public double LowerValue
{
get { return (double)GetValue(LowerValueProperty); }
set { SetValue(LowerValueProperty, value); }
}
public static readonly DependencyProperty LowerValueProperty =
DependencyProperty.Register("LowerValue", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d));
public double UpperValue
{
get { return (double)GetValue(UpperValueProperty); }
set { SetValue(UpperValueProperty, value); }
}
public static readonly DependencyProperty UpperValueProperty =
DependencyProperty.Register("UpperValue", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d));
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(1d));
#endregion
}
}
What I want to do is to set an event for every time MouseUp happens, so that it checks the value of UpperSlider & LowerSlider and will change the border colour of each text box from Orange to Grey if the sliders are not in the range.
Can anyone help?

First, your RangeSlider deals with numeric ranges, so I don't think it makes sense to put month indicators inside the UserControl. I would split those out separately.
First, remove the StackPanel with the text boxes from the RangeSlider Xaml. Create a new DateRangePicker (or similarly named) user control, and add a RangeSlider and the original text boxes. Remove the duplicate property setters from the text boxes, and move them into a Style:
<UserControl x:Class="WpfTest2.DateRangePicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTest2">
<StackPanel>
<local:RangeSlider x:Name="rangeSlider"
Minimum="1" Maximum="12"
LowerValue="1" UpperValue="12" />
<UniformGrid Columns="12" Rows="1" Margin="8,5,20,0">
<UniformGrid.Resources>
<Style TargetType="TextBox">
<Setter Property="Margin" Value="2,0,0,0" />
<Setter Property="FontFamily" Value="Tahoma" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="Focusable" Value="False" />
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="SelectionBrush" Value="{x:Null}" />
<Setter Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}" />
<Setter Property="Foreground">
<Setter.Value>
<MultiBinding Mode="OneWay">
<MultiBinding.Converter>
<local:InRangeConverter />
</MultiBinding.Converter>
<Binding ElementName="rangeSlider" Path="LowerValue" />
<Binding RelativeSource="{RelativeSource Self}" Path="Tag" />
<Binding ElementName="rangeSlider" Path="UpperValue" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</UniformGrid.Resources>
<TextBox Tag="1" Text="Jan" />
<TextBox Tag="2" Text="Feb" />
<TextBox Tag="3" Text="Mar" />
<TextBox Tag="4" Text="Apr" />
<TextBox Tag="5" Text="May" />
<TextBox Tag="6" Text="Jun" />
<TextBox Tag="7" Text="Jul" />
<TextBox Tag="8" Text="Aug" />
<TextBox Tag="9" Text="Sep" />
<TextBox Tag="10" Text="Oct" />
<TextBox Tag="11" Text="Nov" />
<TextBox Tag="12" Text="Dec" />
</UniformGrid>
</StackPanel>
</UserControl>
(Note: If you decide you don't want to split up the date labels from the range slider, just replace the original StackPanel with the UniformGrid from above, and update the bindings to say ElementName="root" instead of ElementName="rangeSlider".)
I used a MultiBinding to set the Foreground. It relies on this custom converter:
public class InRangeConverter : IMultiValueConverter
{
private static readonly SolidColorBrush SelectedBrush =
new SolidColorBrush(Color.FromArgb(0xFF, 0xF7, 0x8A, 0x09));
private static readonly SolidColorBrush UnselectedBrush =
new SolidColorBrush(Color.FromArgb(0x3F, 0xF7, 0x8A, 0x09));
private static readonly object[] ConvertBackResult =
{ DependencyProperty.UnsetValue };
public object Convert(object[] values, Type type, object p, CultureInfo c)
{
if (values?.Length == 3)
{
var lower = values[0] as double?;
var value = values[1] as double?;
var upper = values[2] as double?;
if (value == null)
{
var stringValue = values[1]?.ToString();
if (stringValue != null && double.TryParse(stringValue, out var d))
value = d;
}
if (value >= lower && value <= upper)
return SelectedBrush;
return UnselectedBrush;
}
return Brushes.Gray;
}
public object[] ConvertBack(object value, Type[] types, object p, CultureInfo c)
{
return ConvertBackResult;
}
}
You weren't clear on how you wanted to adjust the colors, so I change the color based on whether the date is in the selected range. You can adjust the logic and the colors as necessary.
Results:
NOTE: Right now, you can set an upper value that's less than the lower value. You should fix that.

Related

Passing image selection from child window to MainPage

I'm working on a UWP FTP front-end application. I've created a UserControl that mimics the form of a standard Windows desktop icon (consisting of a StackPanel containing an Image and a TextBlock) which is to be used as a way of displaying saved favorites. What I'd like is for the user to be able to select any image to be used as the icon for each favorite, but have run into some pretty significant issue with getting this to work, I believe due to the Windows 10 "no access to filesystem" restriction--I haven't figured out that part yet.
As a temporary substitution, I came up with the idea of having a set of icons for the user to select from, all stored within the Assets folder of the application. I've created an IconSelector page/child window (IconSelector.xaml) that pops up when appropriate, allowing the user to select from 8 different Images.
The issue I'm running into is getting the selected Image back to the parent window (MainPage.xaml). I thought of just passing an int from child to parent, and then use that int with an enum to indicate the correct image, but I can't figure out how to pass any parameter at all between child and parent.
I did find this question on SO, but it's for Silverlighbt and doesn't seem to work in UWP (unless I implemented it incorrectly).
Does anybody have any idea on how to accomplish this? Code (relevant portions) pasted below:
MainPage XAML
<Canvas Grid.Column="1" Grid.Row="0" Grid.RowSpan="5" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Image Source="Assets\Red.png" Canvas.ZIndex="200" />
<Border x:Name="addFtpGrid" Visibility="Visible" Canvas.Left="300" Canvas.Top="300" Width="600" Height="350" BorderBrush="{ThemeResource SystemControlBackgroundAccentRevealBorderBrush}" BorderThickness="3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.5*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="1.5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Link name" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5,0" />
<TextBlock Text="Address" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5,0" />
<TextBlock Text="Username" Grid.Column="0" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5,0" />
<TextBlock Text="Password" Grid.Column="0" Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5,0" />
<TextBlock Text="Confirm Password" Grid.Column="0" Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5,0" />
<TextBox x:Name="linkNameEntry" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="1" Grid.Row="0" Margin="5,0" />
<TextBox x:Name="addressEntry" Text="ftp://" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" Margin="5,0" />
<TextBox x:Name="usernameEntry" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="1" Grid.Row="2" Margin="5,0" />
<PasswordBox x:Name="passwordEntry" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="1" Grid.Row="3" Margin="5,0">
</PasswordBox>
<PasswordBox x:Name="confirmPasswordEntry" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="1" Grid.Row="4" Margin="5,0" LostFocus="ConfirmPasswordEntry_LostFocus" />
<Viewbox Grid.Column="2" Grid.Row="0" Grid.RowSpan="4" Margin="5,15,5,0">
<Image x:Name="imageEntry" Source="Assets/SquircleX.png" Tapped="ImageEntry_TappedAsync" />
</Viewbox>
<TextBlock Text="Click image to change" Grid.Column="2" Grid.Row="4" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button x:Name="saveNewFtpLink" Click="SaveNewFtpLink_Click" Content="Save Changes" Grid.Column="0" Grid.Row="5" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10"/>
</Grid>
</Border>
</Canvas>
MainPage C#
private async void ImageEntry_TappedAsync(object sender, TappedRoutedEventArgs e)
{
IconSelector selector = new IconSelector();
selector.Tapped += new TappedEventHandler(selector_Tapped);
ShowDialog(selector);
//List<string> fileTypes = new List<string> { ".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff", ".ico" };
//FileOpenPicker picker = new FileOpenPicker();
//picker.ViewMode = PickerViewMode.Thumbnail;
//picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
//foreach (string type in fileTypes)
//{
// picker.FileTypeFilter.Add(type);
//}
//StorageFile file = await picker.PickSingleFileAsync();
//if(file != null)
//{
// imageEntry.Source = new BitmapImage(new Uri(file.Path));
// Image selectedImage = new Image();
// selectedImage.Source = imageEntry.Source;
// imageEntry = selectedImage;
// imageEntry.UpdateLayout();
// imageToken = StorageApplicationPermissions.FutureAccessList.Add(file);
//}
}
IconSelector XAML
<Page
x:Class="FtpSharp.IconSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FtpSharp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignHeight="175" d:DesignWidth="600"
Background="{ThemeResource ContentDialogBackgroundThemeBrush}">
<Page.Resources>
<Style x:Key="selectionStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="10" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Margin" Value="10,10,5,5" />
<Setter Property="BorderThickness" Value="3" />
</Style>
</Page.Resources>
<Grid VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel x:Name="iconViewer" Orientation="Horizontal" Width="1100">
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpRed.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpOrange.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpYellow.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpGreen.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpBlue.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpPurple.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpPink.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
<Border Style="{StaticResource selectionStyle}">
<Image Source="Assets\FtpTeal.png" Margin="4" Height="96" Tapped="Image_Tapped" />
</Border>
</StackPanel>
</ScrollViewer>
<Button x:Name="commitSelection" Content="Save" Grid.Row="1" Foreground="Black" HorizontalAlignment="Center" Margin="0,10" />
</Grid>
IconSelector C#
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace FtpSharp
{
public sealed partial class IconSelector : Page
{
private static readonly DependencyProperty SelectedIconProperty = DependencyProperty.Register("SelectedIcon", typeof(int),
typeof(IconSelector), new PropertyMetadata(0));
public int SelectedIcon
{
get { return (int)GetValue(SelectedIconProperty); }
set { SetValue(SelectedIconProperty, value); }
}
public IconSelector()
{
this.InitializeComponent();
}
private void Image_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
Image tappedImage = (Image)sender;
Border tappedBorder = (Border)tappedImage.Parent;
SolidColorBrush blue = new SolidColorBrush(Colors.Blue);
foreach (Border border in iconViewer.Children)
{
border.BorderBrush = new SolidColorBrush(Colors.Transparent);
}
tappedBorder.BorderBrush = new SolidColorBrush(Color.FromArgb(255,0,0,255));
}
}
In this case you can either provide the result as a public property of the IconSelector class, or as EventArgs of an event. You already have the SelectedIcon property there, so you can use it. To notify the MainPage that the selection has occurred, you need to add an event to IconSelector - for example DialogCompleted:
public event EventHandler<int> DialogCompleted;
You will trigger this event when the dialog is confirmed by the user:
DialogCompleted?.Invoke(this, SelectedIcon);
Then within MainPage, you need to subscribe to this event:
IconSelector selector = new IconSelector();
selector.DialogCompleted += IconDialogCompleted;
ShowDialog(selector);
And now get the SelectedIcon inside the handler:
private void IconDialogCompleted(object sender, int selectedIcon)
{
//do something with selectedIcon
}

Binding in doesn't seem to work inside a custom DataTemplate (Expander)

Overview
I'm trying to create a custom expander which contains a visual tree where the user can select or deselect nodes. But the tree is not important for now. Important is the header which I had to overwrite so I can show all the information the user needs.
Issue
Somehow the Binding of the textboxes inside the DataTemplate doesn't work at all. No matter what I enter into the fields are always empty and the setter of the DependencyProperty doesn't get called.
Code
<UserControl x:Class="WPF_Test_project.CheckableTree"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid>
<Grid.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="ExpanderToggleButton" TargetType="ToggleButton">
<Path Name="Chevron"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 10 10 L 20 0 Z"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}"
/>
<!-- Change appearance when is expanded -->
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="Chevron" Property="Data" Value="M 0 10 L 10 0 L 20 10 Z" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="MainViewExpander" TargetType="Expander">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Expander">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Name="ContentRow" Height="0" />
</Grid.RowDefinitions>
<Border Name="HeaderBorder"
Grid.Row="0"
BorderThickness="0"
Background="#FFE1E1E1"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<ContentPresenter
Grid.Column="0"
Margin="0"
ContentSource="Header"
RecognizesAccessKey="True"
/>
<ToggleButton
Grid.Column="2"
Margin="4 4 8 4"
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Template="{StaticResource ExpanderToggleButton}"
Background="Black"
/>
</Grid>
</Border>
<Border Name="ContentBorder" Grid.Row="1" BorderThickness="0">
<ContentPresenter Margin="0" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ContentRow" Property="Height" Value="{Binding ElementName=Content, Path=DesiredHeight}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
Margin="4"
/>
<TextBlock Grid.Column="1"
Margin="2"
Text="{Binding ElementName=CT, Path=Header, FallbackValue=Header}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
/>
<TextBlock Grid.Column="2"
Margin="2"
Text="{Binding ElementName=CT, Path=NrOfFeaturesSelected, FallbackValue=5}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
HorizontalAlignment="Right"
/>
<TextBlock Grid.Column="3"
Margin="2"
Text="/"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
HorizontalAlignment="Right"
/>
<TextBlock Grid.Column="4"
Margin="2"
Text="{Binding ElementName=CT, Path=NrOfFeaturesAvailable, FallbackValue=5}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
HorizontalAlignment="Right"
/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<Expander IsExpanded="True" Style="{StaticResource MainViewExpander}">
<TreeView ItemsSource="{Binding ElementName=CT, Path=Items}"
BorderThickness="0"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"
Padding="4"
>
<TreeView.Resources>
<HierarchicalDataTemplate
x:Key="CheckableTreeItemTemplate"
ItemsSource="{Binding ElementName=CT, Path=Items}"
>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
IsChecked="{Binding IsChecked}"
VerticalAlignment="Center"
Visibility="{Binding IsCheckable, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
<Label Grid.Column="1"
Content="{Binding Title}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
/>
<Label Grid.Column="3"
Content="{Binding TagCountDisplayValue}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Visibility="{Binding ShowTagCountDisplayValue, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</Grid>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Expander>
</Grid>
</UserControl>
Class
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace WPF_Test_project
{
/// <summary>
/// Interaction logic for CheckableTree.xaml
/// </summary>
public partial class CheckableTree : UserControl
{
public CheckableTree()
{
InitializeComponent();
}
public int NrOfFeaturesSelected
{
get { return (int)GetValue(NrOfFeaturesSelectedProperty); }
set { SetValue(NrOfFeaturesSelectedProperty, value); }
}
public static readonly DependencyProperty NrOfFeaturesSelectedProperty =
DependencyProperty.Register("NrOfFeaturesSelected", typeof(Int32), typeof(CheckableTree), new UIPropertyMetadata(null));
public int NrOfFeaturesAvailable
{
get { return (int)GetValue(NrOfFeaturesSelectedProperty); }
set { SetValue(NrOfFeaturesSelectedProperty, value); }
}
public static readonly DependencyProperty NrOfFeaturesAvailableProperty =
DependencyProperty.Register("NrOfFeaturesAvailable", typeof(Int32), typeof(CheckableTree), new UIPropertyMetadata(null));
public IEnumerable<object> Items
{
get { return (IEnumerable<object>)GetValue(ItemsProperty); }
set { SetValue(NrOfFeaturesSelectedProperty, value); }
}
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(IEnumerable<object>), typeof(CheckableTree), new UIPropertyMetadata(null));
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(CheckableTree), new UIPropertyMetadata(null));
}
}
Usage
<local:CheckableTree Header="Test" NrOfFeaturesSelected="9">
</local:CheckableTree>
But I always get the Fallback Values. Does anybody know why this happens? Do I have to link the DataTemplate to the Control Class or something?
Solution (Thanks to mm8)
For every binding in the DataTemplate refer to the parent UserControl
<Textbox
...
Text={Binding Path=XY, RelativeSource={RelativeSource AncestorType=UserControl}, FallbackValue=...}"
... />
Try to bind to the Header property of the parent UserControl using a {RelativeSource}:
<TextBlock Grid.Column="1"
Margin="2"
Text="{Binding Path=Header, RelativeSource={RelativeSource AncestorType=UserControl}, FallbackValue=Header}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
/>

Translate DataGrid MouseEvent so I do not have code in View's Code-Behind

I have a working code with a Datagrid as the main control.
I used a Datagrid as it is very easy to bind data into it.
My code requires moving cells into other columns so I always need to check which cell I am on when the mouse is clicked, as well as when it is released.
My current implementation is working as expected.
However, the way I check for the row and cell is through the VIEW's code-behind.
My project leader is looking for an alternative to have this done thru binding as he wants to keep the VIEW's code-behind as clean as possible.
I have tried all I could but I can't find properties which would give me both the cells column and row index.
Please see the code below. (Omitted some of the columns as it would exceed the limit.)
the XAML:
<UserControl x:Class="Widget5.View.WorkItemsDisplay"
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:converter="clr-namespace:Widget5.Converter"
mc:Ignorable="d"
d:DesignHeight="630" Width="690" Padding="0" Margin="0">
<UserControl.Resources>
<converter:RowNumberConverter x:Key="rowNumberConverter" />
<converter:HourSlotToBrushConverter x:Key="hourSlotColorConverter" />
</UserControl.Resources>
<Grid Margin="0" Width="690" HorizontalAlignment="Left" MouseRightButtonUp="Grid_MouseRightButtonUp" MouseUp="Grid_MouseUp">
<Grid.RowDefinitions>
<RowDefinition Height="24"></RowDefinition>
<RowDefinition></RowDefinition>
<!--<RowDefinition Height="30"></RowDefinition>-->
</Grid.RowDefinitions>
<!--<Grid HorizontalAlignment="Left" Height="24" VerticalAlignment="Bottom" Grid.Row="2"
Width="680">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="2" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="2" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Width="48"
Command="{Binding AddCommand}">Add</Button>
<Button Grid.Column="3" Width="48"
Command="{Binding DeleteCommand}">Delete</Button>
<Button Grid.Column="5" Width="48"
Command="{Binding SaveCommand}">Save</Button>
<Button Grid.Column="7" Width="48"
Command="{Binding RefreshCommand}">Refresh</Button>
</Grid>-->
<Grid HorizontalAlignment="Left" Height="24" VerticalAlignment="Top" Width="690" Grid.Row="0"
Background="LightGray">
<Grid.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="10"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="22"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="123"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="1" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="2" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="3" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="4" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="5" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="6" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="7" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="8" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="9" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="10" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="11" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="12" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="13" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="14" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="15" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="16" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="17" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="18" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="19" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="20" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="21" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="22" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="23" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="24" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="25" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="26" BorderThickness="1,1,0,1" BorderBrush="Black"/>
<Border Grid.Column="27" BorderThickness="1,1,1,1" BorderBrush="Black"/>
<TextBlock Text="NO" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" FontSize="12"/>
<TextBlock Text="削" HorizontalAlignment="Center" Grid.Column="1" VerticalAlignment="Center" Margin="0" FontSize="12"/>
<TextBlock Text="中項目名称" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" FontSize="12"/>
<TextBlock Text="回数" HorizontalAlignment="Center" Grid.Column="3" VerticalAlignment="Center" Margin="0" FontSize="12"/>
<TextBlock Text="5" Grid.Row="0" Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="6" Grid.Row="0" Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="7" Grid.Row="0" Grid.Column="6" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="8" Grid.Row="0" Grid.Column="7" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="9" Grid.Row="0" Grid.Column="8" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="10" Grid.Row="0" Grid.Column="9" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="11" Grid.Row="0" Grid.Column="10" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="12" Grid.Row="0" Grid.Column="11" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="13" Grid.Row="0" Grid.Column="12" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="14" Grid.Row="0" Grid.Column="13" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="15" Grid.Row="0" Grid.Column="14" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="16" Grid.Row="0" Grid.Column="15" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="17" Grid.Row="0" Grid.Column="16" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="18" Grid.Row="0" Grid.Column="17" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="19" Grid.Row="0" Grid.Column="18" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="20" Grid.Row="0" Grid.Column="19" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="21" Grid.Row="0" Grid.Column="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="20" Grid.Row="0" Grid.Column="21" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="23" Grid.Row="0" Grid.Column="22" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="0" Grid.Row="0" Grid.Column="23" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="1" Grid.Row="0" Grid.Column="24" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="2" Grid.Row="0" Grid.Column="25" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="3" Grid.Row="0" Grid.Column="26" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
<TextBlock Text="4" Grid.Row="0" Grid.Column="27" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
</Grid>
<DataGrid Name="ScheduleDG" ItemsSource="{Binding ScheduleTable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="1" AutoGenerateColumns="False" HeadersVisibility="None"
IsReadOnly="False" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden"
SelectionUnit="CellOrRowHeader" SelectionMode="Extended" Padding="0" FontSize="10" BorderThickness="1" BorderBrush="Black" HorizontalAlignment="Left" Width="690"
Margin="0,-1,-2,0" Height="Auto" AllowDrop="True" RowHeight="18"
PreviewMouseLeftButtonUp="ScheduleTable_PreviewMouseLeftButtonUp"
PreviewMouseLeftButtonDown="ScheduleTable_PreviewMouseLeftButtonDown" MouseMove="ScheduleDG_MouseMove">
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.CellSelectedCommand}"
CommandParameter="{Binding SelectedCells, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.StartCellCommand}"
CommandParameter="{Binding CurrentCell, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseRightClick">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.RightClickCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>-->
<DataGrid.Columns>
<DataGridTextColumn Header="NO" Width="22" IsReadOnly="True">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontSize" Value="10" />
<Setter Property="Margin" Value="0"/>
</Style>
</DataGridTextColumn.HeaderStyle>
<DataGridTextColumn.Binding>
<MultiBinding Converter="{StaticResource rowNumberConverter}">
<Binding />
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}" />
</MultiBinding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTemplateColumn Header="削">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="TestCheckBox" VerticalAlignment="Center" HorizontalAlignment="Center"
IsChecked="{Binding isSelected, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="中項目名称" Binding="{Binding TaskName}" Width="123"/>
<DataGridTextColumn Header="回数" Width="30"/>
<!--<DataGridTemplateColumn Header="5" MaxWidth="10">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Background="{Binding _5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="False">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}},
Path=DataContext.StartCellCommand}"
CommandParameter="{Binding CurrentCell, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>-->
<DataGridTextColumn Header="5" MaxWidth="10" FontSize="8" Width="10" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding _5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Margin" Value="-1" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="" MaxWidth="10" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding _5_5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Margin" Value="-1" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="6" MaxWidth="10" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding _6, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Margin" Value="-1" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="" MaxWidth="10" IsReadOnly="True" >
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding _3_5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Margin" Value="-1" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="4" MaxWidth="10" IsReadOnly="True" >
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding _4, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Margin" Value="-1" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="" MaxWidth="9" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding _4_5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Margin" Value="-1" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
the code-behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using MainModule.Infrastructure.Interface;
using Widget5.ViewModel;
namespace Widget5.View
{
/// <summary>
/// Interaction logic for ExcelDisplay.xaml
/// </summary>
[Export(typeof(IMainModulePage))]
[ExportMetadata("WidgetName", "Widget5")]
[ExportMetadata("MenuNo", 1)]
[ExportMetadata("PageTitle", "WorkItemsPage")]
public partial class WorkItemsDisplay : UserControl, IMainModulePage
{
public WorkItemsDisplay()
{
DataContext = eVM;
InitializeComponent();
}
// inherit
public string WidgetName
{
get { return "Widget5"; }
}
public int MenuNo
{
get { return 1; }
}
public string PageTitle
{
get { return "WorkItemsPage"; }
}
ExcelGridViewModel eVM = new ExcelGridViewModel();
bool isClicked;
List<int> trueCells;
bool hasMoved;
private void ScheduleTable_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
// iteratively traverse the visual tree
while ((dep != null) &&
!(dep is DataGridCell))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
if (dep is DataGridCell)
{
DataGridCell cell = dep as DataGridCell;
DataGridCellInfo cellInfo = new DataGridCellInfo(cell);
while ((dep != null) && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}
DataGridRow row = dep as DataGridRow;
hasMoved = false;
if (eVM.DoEndCell(cell, row, hasMoved))
ScheduleDG.UnselectAllCells();
ScheduleDG.CurrentCell = cellInfo;
}
isClicked = false;
}
private void ScheduleTable_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
// iteratively traverse the visual tree
while ((dep != null) &&
!(dep is DataGridCell))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
if (dep is DataGridCell)
{
DataGridCell cell = dep as DataGridCell;
while ((dep != null) && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}
DataGridRow row = dep as DataGridRow;
trueCells = eVM.DoStartCell(cell, row);
}
isClicked = true;
}
private void Grid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
private void ScheduleDG_MouseMove(object sender, MouseEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
// iteratively traverse the visual tree
while ((dep != null) &&
!(dep is DataGridCell))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
if (dep is DataGridCell)
{
DataGridCell cell = dep as DataGridCell;
DataGridCellInfo cellInfo = new DataGridCellInfo(cell);
while ((dep != null) && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}
DataGridRow row = dep as DataGridRow;
if (isClicked && (trueCells.Count <= 1))
{
hasMoved = true;
eVM.DoEndCell(cell, row, hasMoved);
}
}
}
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
isClicked = false;
hasMoved = false;
}
}
}
EDIT
I proceeded to multibind the datagridcell's column and datacontext properties as parameters for my command. An option I started before but set aside due to time constraints. Instead of looking for the datagridrow's index, I used the datacontext to compare to my viewmodel. Did the trick.
The general way to achieve your requirement is to implement an ICommand type Attached Property for each event that you want to replace. The basic idea is this... add an ICommand Attached Property with a PropertyChangedCallback handler. In this handler (which will be called when an ICommand is data bound to this property), attach a handler to the event that you want to handle. Then, when that event is called, just execute the ICommand instance. So you can handle the event in your view model via the ICommand instance. Here is an example using the PreviewKeyDown event:
public static DependencyProperty OnEnterKeyDownProperty = DependencyProperty.RegisterAttached("OnEnterKeyDown", typeof(ICommand), typeof(TextBoxProperties), new UIPropertyMetadata(null, OnOnEnterKeyDownChanged));
public static ICommand GetOnEnterKeyDown(DependencyObject dependencyObject)
{
return (ICommand)dependencyObject.GetValue(OnEnterKeyDownProperty);
}
public static void SetOnEnterKeyDown(DependencyObject dependencyObject, ICommand value)
{
dependencyObject.SetValue(OnEnterKeyDownProperty, value);
}
public static void OnOnEnterKeyDownChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = dependencyObject as TextBox;
if (e.OldValue == null && e.NewValue != null) textBox.PreviewKeyDown += TextBox_OnEnterKeyDown;
else if (e.OldValue != null && e.NewValue == null) textBox.PreviewKeyDown -= TextBox_OnEnterKeyDown;
}
private static void TextBox_OnEnterKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter || e.Key == Key.Return)
{
TextBox textBox = sender as TextBox;
ICommand command = GetOnEnterKeyDown(textBox);
if (command != null && command.CanExecute(textBox)) command.Execute(textBox);
}
e.Handled = false;
}
Alternative would be to work with properties DataGrid already provides to you and/or to define few other attached properties supporting you to get the job done.
I would try to work with properties like SelectedItem, SelectedValue, CurrentItem, CurrentCell.
Futhermore if a behavior couldnt be handled with those properties from above I would create an attached property and use a style for cells with triggers changing the attached property. Binding will transmit all the changes from the attached property to the ViewModel.
In the end you will have just communication between ViewModel and View.
Here are few links:
http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.currentitem%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.selectedvalue%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.selecteditem%28v=vs.110%29.aspx
They should be all bindable
Edit:
Link to MSDN MultiBinding Page:
http://msdn.microsoft.com/en-us/library/system.windows.data.multibinding%28v=vs.110%29.aspx

Table In XAml Windows Store App

My TABLE code
ItemS Control Working Perfectly But I need only one listview inside listview help i get problem in
c Get Set Class I need a Single List
Hi I Need To Generate A Table In My Metro APP BUT I GET WRONG OUTPUT PLEASE HELP I BIND HEADER AND CONTENTS SEPERATELY USING LIST
C# CODE
foreach (var item in itemsreceiveds)
{
variable2.Add(new contentdata() { firstdata = item.getFirstData, seconddata = item.getSecondData, thirddata = item.getThirdData, headers = item.getFieldName });
}
var groupedPersons = variable2.Select((emp) => new { sectionName = emp.headers }).ToList().Distinct();
foreach (var s in groupedPersons)
{
firstheader = s.sectionName;
string[] sepword = firstheader.Split('#');
firstheader = sepword[0].ToUpper();
secondheader = sepword[1].ToUpper();
thirdheader = sepword[2].ToUpper();
variableheader.Add(new contentdataheader(firstheader,secondheader,thirdheader));
groupListView.ItemsSource = variableheader;
}
//SUBITEM
foreach (var person in variable2)
{
subdata.Add(new subitems(person.firstdata, person.seconddata, person.thirddata));
}
itemListViewss.ItemsSource = subdata;
XAML
<ListView Name="groupListView" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsSwipeEnabled="True" SelectionMode="None" Grid.ColumnSpan="3" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Border x:Name="bordermenu" BorderBrush="Black" BorderThickness="1" Grid.Column="1" Grid.Row="0" Width="150">
<TextBlock Foreground="Red" Text="{Binding Firstheader}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border x:Name="bordermenu2" BorderBrush="Black" BorderThickness="1" Grid.Column="2" Grid.Row="0" Width="150">
<TextBlock Foreground="Red" Text="{Binding Secondheader}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border x:Name="bordermenu3" BorderBrush="Black" BorderThickness="1" Grid.Column="3" Grid.Row="0" Width="150">
<TextBlock Foreground="Red" Text="{Binding Thirdheader}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Name="itemListViewss" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsSwipeEnabled="True" SelectionMode="None" Grid.ColumnSpan="3" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Border x:Name="bordersubmenu" BorderBrush="Black" BorderThickness="1" Grid.Column="1" Grid.Row="1" Width="150">
<TextBlock Foreground="Blue" Text="{Binding dynamic}" x:Name="submenu" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Border x:Name="bordersubmenu2" BorderBrush="Black" BorderThickness="1" Grid.Column="2" Grid.Row="1" Width="150">
<TextBlock Foreground="Blue" Text="{Binding p1}" x:Name="submenu2" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Border x:Name="bordersubmenu3" BorderBrush="Black" BorderThickness="1" Grid.Column="3" Grid.Row="1" Width="150">
<TextBlock Foreground="Blue" Text="{Binding p2}" x:Name="submenu3" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I Get Ouput As
But I Need Output As This
Here's the simplest answer - a working demo.
I didn't do everything for you, mate, but I sure did a lot. You'll have to code a little to get it just how you like. If you are using a custom control suite, most of this might be done for you. If not, this will get you down the road. Far down the road.
Take this code behind:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
}
public class Datum
{
public DateTime Date { get; set; }
public string Year { get { return Date.ToString("yyy"); } }
public string Month { get { return Date.ToString("MMMM"); } }
public string Day { get { return Date.ToString("dd"); } }
public string Weekday { get { return Date.ToString("dddd"); } }
}
public class ViewModel
{
public ViewModel()
{
// data
var _Data = Enumerable.Range(1, 20)
.Select(x => new Datum { Date = DateTime.Now.Add(TimeSpan.FromDays(x * 14)) });
Data = new ObservableCollection<Datum>(_Data);
}
public ObservableCollection<Datum> Data { get; private set; }
}
And then try this XAML:
<Page.DataContext>
<local:ViewModel/>
</Page.DataContext>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Grid Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="White" />
<Setter Property="Padding" Value="5" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
</Style>
</Grid.Resources>
<Border Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="4">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<TextBlock VerticalAlignment="Center" TextAlignment="Right">
<Run Text="Search" />
<LineBreak />
<Run Text="Data" />
</TextBlock>
<TextBox Width="100" />
</StackPanel>
</Border>
<Border Grid.Column="0" Grid.Row="1"><TextBlock Text="Year" /></Border>
<Border Grid.Column="1" Grid.Row="1"><TextBlock Text="Month" /></Border>
<Border Grid.Column="2" Grid.Row="1"><TextBlock Text="Day" /></Border>
<Border Grid.Column="3" Grid.Row="1"><TextBlock Text="Weekday" /></Border>
</Grid>
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="5,0" />
</Style>
</Grid.Resources>
<TextBlock Grid.Column="0" Text="{Binding Year}" />
<TextBlock Grid.Column="1" Text="{Binding Month}" />
<TextBlock Grid.Column="2" Text="{Binding Day}" />
<TextBlock Grid.Column="3" Text="{Binding Weekday}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Width="400">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="White" />
<Setter Property="Padding" Value="5" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
</Style>
</Grid.Resources>
<Border Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="4">
<TextBlock Text="Showing 1 to 10 of 371" HorizontalAlignment="Right" />
</Border>
</Grid>
</StackPanel>
</Grid>
You should get something like this:
To add to Jerry's XAML in his answer. You can replace the ItemsControl with a ListBox (same template/itemTemplate modifications) to get the same view, but also the ability to use SelectedIndex, but I don't know if that applies to this question.
Note: I did find you need to add a Width to the ListBox. You can't just let the Grid in the ItemTemplate do it.
Maybe you're looking for something like this.
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Fill="Black" Grid.ColumnSpan="2" Grid.Row="0" />
<TextBlock Text="Integer" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" Grid.Row="0" Grid.Column="0" FontSize="14" />
<TextBlock Text="String" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" Grid.Row="0" Grid.Column="1" FontSize="14" />
<ListView x:Name="ListViewDisplay" ItemsSource="{Binding}" Grid.Row="1" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="Black" Background="White" RequestedTheme="Light">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Integer}" Margin="5" Grid.Column="0" FontSize="14" />
<TextBlock Text="{Binding String}" Margin="5" Grid.Column="1" FontSize="14" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Behind code:
public sealed partial class SamplePage : Page
{
ObservableCollection<ROWS> r = new ObservableCollection<ROWS>();
public SamplePage()
{
this.InitializeComponent();
r.Add(new ROWS { Integer = 1, String = "ONE" });
r.Add(new ROWS { Integer = 2, String = "TWO" });
r.Add(new ROWS { Integer = 3, String = "THREE" });
r.Add(new ROWS { Integer = 4, String = "FOUR" });
r.Add(new ROWS { Integer = 5, String = "FIVE" });
ListViewDisplay.ItemsSource = r;
}
}
public class ROWS {
public int Integer { get; set; }
public string String { get; set; }
}
Result:

Listbox item as Listbox should clear the selection of its item when other item's item is selected?

I have a ListBox as a ListboxItem in the mainlist. In one item that is ListBox I select an item. This selection should be cleared when I have another item selected from the other items ListBox. Code is as below:
<ListBox x:Name="lst" Grid.Row="3" BorderThickness="0" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ItemsSource="{Binding MessageCollection}" ScrollViewer.CanContentScroll="False" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Width="{Binding RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type Grid}},Path=ActualWidth}" HorizontalAlignment="Stretch">
<Border Background ="#ffffff" BorderBrush="#dddddd" BorderThickness="0,1,0,0" Height="30" >
<TextBlock Text="{Binding Date, StringFormat={}{0:dd MMMM yyyy}}" VerticalAlignment="Center" FontWeight="Bold" FontSize="12" FontFamily="Tahoma" Foreground="#7a7a7a" HorizontalAlignment="Center" />
</Border>
<ListBox x:Name="lstMsgs" HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Hidden" HorizontalContentAlignment="Stretch" ItemsSource="{Binding MessageList}" SelectedItem="{Binding DataContext.SelectedMessage,Mode=TwoWay,ElementName=me}" Background="Transparent" BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<Border x:Name="brdItem" BorderBrush="#dddddd" BorderThickness="0,1,0,0" >
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#f1f1f1" Offset="0"/>
<GradientStop Color="#efefef" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid Height="30" HorizontalAlignment="Stretch" VerticalAlignment="Center" ScrollViewer.HorizontalScrollBarVisibility="Hidden" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<Image x:Name="img" Grid.Column="1" Visibility="Collapsed" HorizontalAlignment="Center" Source="Images\icon1.png" Stretch="None" Margin="10,0,0,0" />
<TextBlock Text="Ershad Sheikh" VerticalAlignment="Center" Foreground="#2b2a2a" FontSize="12" Grid.Column="3" />
<TextBlock Text="{Binding GroupMessage}" HorizontalAlignment="Left" Foreground="#7a7a7a" FontSize="11" Grid.Column="5" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
<TextBlock Text="{Binding Date, StringFormat={}{0: hh:mm:ss tt}}" FontWeight="Bold" FontSize="12" Foreground="#2378a0" Grid.Column="7" VerticalAlignment="Center" HorizontalAlignment="Right" />
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsReplyPresent}" Value="True">
<Setter TargetName="img" Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="brdItem" Property="Background" Value="#e5e9eb" >
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="#e5e9eb"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
</ListBox.Resources>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="#e5e9eb"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
</ListBox.Resources>
</ListBox>
You can explicitly null the SelectedItem whenever the ListBox loses focus, i.e you have to handle the LostFocus event.
You could add the event handler to the ListBox and handle the event in the code behind.
XAML Change:
<ListBox x:Name="lstMsgs" HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Hidden" HorizontalContentAlignment="Stretch" ItemsSource="{Binding MessageList}" SelectedItem="{Binding DataContext.SelectedMessage,Mode=TwoWay,ElementName=me}" Background="Transparent" BorderThickness="0" LostFocus="lstMsgs_LostFocus">
Code Behind:
private void lstMsgs_LostFocus(object sender, RoutedEventArgs e)
{
ListBox listBox = sender as ListBox;
if (listBox != null)
{
listBox.SelectedItem = null;
}
}
Method 2:
You could achieve the same result by using a DependencyProperty to handle the LostFocus event.
ListBoxExtension.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public static class ListBoxExtension
{
public static readonly DependencyProperty NullSelectedItemOnLostFocusProperty =
DependencyProperty.RegisterAttached("NullSelectedItemOnLostFocus", typeof(bool), typeof(ListBoxExtension), new UIPropertyMetadata(false, OnNullSelectedItemOnLostFocusChanged));
public static bool GetNullSelectedItemOnLostFocus(DependencyObject d)
{
return (bool)d.GetValue(NullSelectedItemOnLostFocusProperty);
}
public static void SetNullSelectedItemOnLostFocus(DependencyObject d, bool value)
{
d.SetValue(NullSelectedItemOnLostFocusProperty, value);
}
private static void OnNullSelectedItemOnLostFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool nullSelectedItemOnLostFocus = (bool)e.NewValue;
ListBox listBox = d as ListBox;
if (listBox != null)
{
if (nullSelectedItemOnLostFocus)
listBox.LostFocus += NullSelectedItem;
else
listBox.LostFocus -= NullSelectedItem;
}
}
public static void NullSelectedItem(object sender, RoutedEventArgs e)
{
ListBox listBox = sender as ListBox;
if (listBox != null)
{
listBox.SelectedItem = null;
}
}
}
}
XAML Change 1: Add namespace in which the ListBoxExtension class is present - xmlns:loc="clr-namespace:WpfApplication1"
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
XAML Change 2: Changing the DependencyProperty - loc:ListBoxExtension.NullSelectedItemOnLostFocus="True"
<ListBox x:Name="lstMsgs" HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Hidden" HorizontalContentAlignment="Stretch" ItemsSource="{Binding MessageList}" SelectedItem="{Binding DataContext.SelectedMessage,Mode=TwoWay,ElementName=me}" Background="Transparent" BorderThickness="0" loc:ListBoxExtension.NullSelectedItemOnLostFocus="True">

Categories