I have Listbox with ListItemTemplate. There are two commands I want attach with each list item.
1) PreviewMouseLeftButtonDown : I use this even when for drag and drop functionality. user press button event gets fired and I came to know how many items user has selected for dragging.
2) PreviewMouseLeftButtonUp: I want to use this when user release mouse from list item. (But issue is this even never gets fired. It seems like 1st event taking control of both.
Here is my code. Pls help.
<DataTemplate x:Key="ListItemTemplate">
<Grid Margin="0" Width="58" Height="58" x:Name="OuterGrid">
<Border x:Name="OuterBorder" BorderBrush="{DynamicResource ContentToGreyedOutBrush}" BorderThickness="0" Margin="0" Background="Transparent" Grid.Column="0" Grid.Row="0"
ClipToBounds="True" CornerRadius="0">
<Border x:Name="InnerBorder" BorderBrush="Transparent" BorderThickness="1" Margin="0" Background="Transparent" CornerRadius="0">
<Grid>
<Image Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding Path=FileName,Converter={StaticResource FileNameImageConverter}}"
Width="50" Height="50">
</Image>
<ToggleButton x:Name="zoomButton" Grid.Column="0" Grid.Row="0" Margin="0" HorizontalAlignment="Right" HorizontalContentAlignment="Right" VerticalAlignment="Bottom"
VerticalContentAlignment="Bottom" Background="Transparent" Cursor="Hand" Template="{StaticResource ZoomTemplate}" Width="20" Height="20" Visibility="Collapsed">
</ToggleButton>
</Grid>
</Border>
</Border>
<ac:CommandBehaviorCollection.Behaviors>
<ac:BehaviorBinding Event="PreviewMouseLeftButtonDown" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}},Path=DataContext.DragItemSelectedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"/>
<ac:BehaviorBinding Event="PreviewMouseLeftButtonUp" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}},Path=DataContext.MouseUPCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"/>
</ac:CommandBehaviorCollection.Behaviors>
</Grid>
</DataTemplate>
It looks like you're trying to do dragging of the item to a different location outside the original bounds. In this case the up event would be firing on the new control over which the mouse is located when it is released, not the control that you started dragging. To make this work you need to make sure to capture the mouse when starting a drag operation.
Related
I have Custom control which uses control template as shown in below code block. I need to show popup when user left clicks on the control. Once he/she clicks outside the pop up, it should close.
With MouseLeftButtonUp, the pop up is displayed however stays open on clicking outside the popup.
Please note I have set focus on on popup listbox element as soon as pop opens using behaviours:Focus
<ControlTemplate x:Key="ControlWithPopup" TargetType="local:CustomizedControl">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<ei:ChangePropertyAction
PropertyName="IsDropDownOpen"
TargetObject="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}}"
Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
<Popup
x:Name="Popup1"
Width="100"
MinWidth="80"
MaxHeight="300"
AllowsTransparency="true"
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}"
Placement="Center"
PlacementTarget="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}}"
PopupAnimation="Fade"
StaysOpen="False">
<Border
Background="{DynamicResource SomeBackgroundBrush}"
BorderBrush="{DynamicResource SomeBorderBrush}"
BorderThickness="1"
TextElement.Foreground="{DynamicResource SomeFontBrush}">
<ListBox
x:Name="List1"
ItemTemplate="{TemplateBinding DropDownTemplate}"
ItemsSource="{Binding Path=ListSource, RelativeSource={RelativeSource Mode=TemplatedParent}}"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding Path=SelectedItem, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}"
Style="{DynamicResource ListBoxNormalStyle}"
VirtualizingPanel.IsVirtualizing="False">
</ListBox>
</Border>
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding IsOpen, ElementName=Popup1}" Value="True">
<behaviours:ScrollIntoCenterView TargetObject="{Binding ElementName=List1}" />
<behaviours:Focus TargetObject="{Binding ElementName=List1}" />
</ei:DataTrigger>
</i:Interaction.Triggers>
</Popup>
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent"
BorderThickness="1">
<TextBlock
x:Name="Presenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="11"
FontWeight="ExtraBold"
Text="{Binding SelectedValue}" />
</Border>
</Grid>
</Border>
</ControlTemplate>
Note -
- Also note, i dont want to set StayOpen to True due to some reason outside the scope of the problem. I want to achieve it using StayOpen set to False
I have a stackpanel that contains many elements including buttons. I am not able to fire a method through ICommands. It works through adding an event handler in the code behind for the Button.Click event. Since, I am following a MVVM pattern, I want to fire a command. Also, this stackpanel is a datatemplate for my listviewitem.
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" IsHitTestVisible="True">
<Button Cursor="Hand" Command="{Binding MoveImageUp}">
<Button.Background>
<ImageBrush ImageSource="..."/>
</Button.Background>
</Button>
<Grid>
<Image Source="{Binding Path=Image}"/>
<TextBlock Height="20" Width="20" Text="{Binding Path=Order}" Opacity="0.8" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
<GridSplitter HorizontalAlignment="Center" Padding="1" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
I have tried setting IsHitTestVisibile to true, does not work.
There was no DataContext set for the button. Thanks #Foggy Finder
<Button Cursor="Hand" Command="{Binding ElementName=ImagesList, Path=DataContext.MoveImageUp}" CommandParameter="{Binding}">
So I'm adding my views directly to the TabControl's Items collection at runtime (instead of creating TabItems around them and addings those TabItems to TabControl). The views expose a property (wrapper around a ViewModel property of the same name) named HasChanges that I want to bind to TabItem's Header to show a Asterisk (*) sign to identify tabs with unsaved changes, just like VS does. I have already tried using DataTemplates but am having trouble accessing the view object in the DataTemplate. What's the correct way of doing this? Here's one of my several attempts:
<TabControl.ItemTemplate>
<DataTemplate DataType="UserControl">
<StackPanel Orientation="Horizontal" Margin="0" Height="22">
<TextBlock VerticalAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource AncestorType=UserControl}}" />
<TextBlock Text="*" Visibility="{Binding HasChanges, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource B2VConverter}}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
Note that I'm trying two different binding methods for the two TextBlocks, none of which is working. My views inherit from UserControl and expose properties HasChanges and HeaderText.
OK. I solved it myself. For anyone else trying to implement a VS-like Close button and unsaved changes asterisk, here's the template:
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0" Height="22">
<TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem}, Path=Content.HeaderText}" />
<TextBlock Text=" *" ToolTip="Has unsaved changes" Visibility="{Binding Content.DataContext.HasChanges, RelativeSource={RelativeSource AncestorType=TabItem}, Converter={StaticResource B2VConverter}}" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Width="18" Height="18"
Margin="6,0,0,0" Padding="0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Center"
Command="{Binding DataContext.TabClosingCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"
VerticalAlignment="Center" Focusable="False">
<Grid Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Line StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Gray" X1="1" Y1="1" X2="9" Y2="9" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Line StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Gray" X1="1" Y1="9" X2="9" Y2="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Button>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
Results in an elegant drawing-based button with a flat-look. Your View must implement Boolean HasChanges and HeaderText properties, plus you need to define a BooleanToVisibilityConverter in your resources section, named B2VConverter.
I am trying to use the accordion control in XAML but am unable to change the dark blue background that is used as default. I've manage to stumble upon a few other people having the same problem but with no solutions posted. The only answer I have found thus far involves using Expression Studio, but I unfortunately do not own a copy.
See below the designer code, there's not a whole lot there at the moment, I've tried setting the background property on each element but get no result on any of them.
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="289"
Width="500"
xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit">
<Grid>
<my:Accordion HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<my:AccordionItem x:Name="item1" Header="Item 1">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
</Grid>
</my:AccordionItem>
<my:AccordionItem x:Name="item2" Header="Item 2">
</my:AccordionItem>
<my:AccordionItem x:Name="item3" Header="Item 3">
</my:AccordionItem>
</my:Accordion>
</Grid>
</Window>
Take a look at this MSDN Forum thread of someone having the same problem. Also be aware this control is of Preview quality which according to CodePlex is equivalant to an Alpha release.
From above link:
The key part is binding to the actual outer grid. For some reason, the accordion item isn't providing a width/height for the inner grid to stretch to, so you have to bind it to something "higher up" so to speak.
I tested it and it does work, It does give designer errors of Object reference not set to an instance of an object It does compile and run though.
<Grid>
<my:Accordion HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<my:AccordionItem x:Name="item1" Header="Item 1">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White"
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid}}, Path=ActualHeight}">
</Grid>
</my:AccordionItem>
<my:AccordionItem x:Name="item2" Header="Item 2">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White"
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid}}, Path=ActualHeight}">
</Grid>
</my:AccordionItem>
<my:AccordionItem x:Name="item3" Header="Item 3">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White"
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid}}, Path=ActualHeight}">
</Grid>
</my:AccordionItem>
</my:Accordion>
</Grid>
Here My TextBox text is being bind to child text box in contentemplate but how to apply along with default style and validation errors to the child textbox in content template.
<TextBox x:Name="tbIdNumber" Width="110" Height="20" Text="{Binding IdNumber, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" >
<TextBox.Template>
<ControlTemplate TargetType="TextBox" >
<StackPanel Orientation="Horizontal" >
<Image Height="10" Width="20" Source="Images/bullet_darkblue.PNG" />
<TextBox Width="90" Tag="{Binding RelativeSource={RelativeSource TemplatedParent}}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent},Path=DataContext, Mode=TwoWay}"
Text="{Binding Path=Text ,RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" >
</TextBox>
</StackPanel>
</ControlTemplate>
</TextBox.Template>
</TextBox>
It is very unusual to define the control template for TextBox control with a TextBox. I suggest you not pursue the path above.
You should instead start off with the default ControlTemplate for a TextBox here (Warning: it is very complex). It contains all the necessary visual states for validation, focused, etc.
From what I observe, you want to add an image next to the textbox. You should be able to add an image element inside the Grid and then perhaps adjust the margin on the Border. Here's a snippet:
<Image Height="10" Width="20" Source="Images/bullet_darkblue.PNG" />
<Border Margin="20,10,0,0"
x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer x:Name="ContentElement" Padding="{TemplateBinding Padding}"
BorderThickness="0" IsTabStop="False"/>
</Border>