|
Try something like this:
public class EnumExcludeFilterConverter : IValueConverter
{
private static readonly char[] Separators = { ';' };
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string filters = parameter == null ? String.Empty : parameter.ToString();
if (string.IsNullOrWhiteSpace(filters)) return value;
Array allValues = value as Array;
if (allValues == null || allValues.Length == 0) return value;
Type enumType = value.GetType().GetElementType();
if (!enumType.IsEnum) return value;
ICollection<string> splitFilters = filters.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
if (splitFilters.Count == 0) return value;
List<Enum> result = new List<Enum>(allValues.Length);
foreach (Enum item in allValues)
{
string itemName = Enum.GetName(enumType, item);
if (!splitFilters.Contains(itemName))
{
result.Add(item);
}
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
That did it. Thank you sir!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I have a listbox that is used for the user to either drag a file into or select via the Open File dialog.
The files in the list are displayed as hyperliks. Here's my XAML
<ListBox Grid.Row="1"
x:Name="filesBox"
AllowDrop="True"
Grid.Column="2"
BorderBrush="SteelBlue"
BorderThickness="1"
VerticalAlignment="Stretch"
ItemsSource="{Binding Attachments}"
SelectedItem="{Binding SelectedAttachment}"
Margin="2"
Drop="ListBox_Drop">
<pre>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="14">
<Hyperlink>
<TextBlock Text="{Binding FileName}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ElementName=attachmentView, Path=DataContext.OpenFileCommand}"
CommandParameter="{Binding }"/>
</i:EventTrigger>
<i:EventTrigger EventName="ListBox_Drop">
<i:InvokeCommandAction Command="{Binding ElementName=attachmentView, Path=DataContext.DragDropCommand}"
CommandParameter="{Binding }"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
The problem is that unless the listbox item is selected, the link doesn't work. If I click on the area around the link to select the list item, then the link works.
I didn't poste the code behind because it works as long as the listbox item is selected. So, how do I select the listbox item when the link is clicked? Or somehow otherwise solve this?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
"Preview" the event as it tunnels down and "select" when the "target" in the event argument matches the one you want. Flag as "handled" as appropriate.
Or simply handle the event yourself once the target (link) is determined.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Ya but preview WHAT event? The hyperlink doesn't respond at all without the list item selected
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Is there a reason the triggers are defined on the TextBlock within the Hyperlink , rather than on the Hyperlink itself?
IIRC, the Click event for an element without a background colour doesn't fire unless you manage to click precisely on the text itself. Have you tried setting the background colour to Transparent ?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
In my utility WPF library I (reinvented the wheel, yeah yeah, I know..) created a Behaviors attached property of type BehaviorList .
static DependencyPropertyKey BehaviorsKey = DependencyProperty.RegisterAttachedReadOnly(
"PrivateBehaviors",
typeof(BehaviorList),
typeof(Behavior),
new UIPropertyMetadata(null));
public static DependencyProperty BehaviorsProperty = BehaviorsKey.DependencyProperty;
public static BehaviorList GetBehaviors(DependencyObject target)
{
var result = (BehaviorList)target.GetValue(BehaviorsProperty);
if (result == null)
{
result = new BehaviorList(target);
target.SetValue(BehaviorsKey, result);
}
return result;
}
then I used this property in XAML to add my own custome behavior type:
<Slider>
<gx:Behavior.Behaviors>
<local:DragLayerGroupBehavior/>
</gx:Behavior.Behaviors>
</Slider>
and here are the class involved
public class BehaviorList : IList<Behavior>, System.Collections.IList
{
}
public class DragLayerGroupBehavior : Behavior
{
}
This works well and good (at runtime) but the designer has red underlines and show the following errors:
Error XLS0503, A value of type 'DragLayerGroupBehavior' cannot be added to a collection or dictionary of type 'BehaviorList'.
Error XDG0048, The specified value cannot be assigned to the collection. The following type was expected: "Behavior".
So the question is, how to "solve" those errors, i.e. unconfused VisualStudio WPF designer?
Is there a particular interface I need to implement, some attribute to use, or something?
|
|
|
|
|
I'm finding (now) that even in design mode, the "IDE" is running my constructors AND firing "Loaded" events.
So, while your app may initialize (and run) properly in "run" mode, it may fail due to incomplete initialization in "design mode".
In UWP (WPF?), I am now also seeing "live" UI changes while in debug mode and changing XAML.
(Missed the announcement if there was one).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
It's a good point!
However, unfortunately, that doesn't seem to be the problem in my particular case...
|
|
|
|
|
I have four controls in a horizontal row.
The first and third control shouöd automatically resize and fill the available space when resizing the MainWindow. The second and forth controls have a static width and I don't want them to change horizontally in size. All four controls should fill vertically.
I have almost solved it with an UniformGrid as container for the four controls.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<UniformGrid Columns="4">
<Rectangle Fill="Blue" />
<Rectangle Fill="Lime" Width="20" />
<Rectangle Fill="Red" />
<Rectangle Fill="Yellow" Width="20" />
</UniformGrid>
</Window>
Run the example and resize the window.
* The blue and red rectangle will resize appropriately horizontally and fill vertically.
* The green and yellow rectangle only fills vertically.
But I cannot understand how to fill/remove the white spaces to the left of all rectangles.
Any suggestions?
|
|
|
|
|
The columns in a UniformGrid will always be the same width. Since you have four columns, each column will be ¼ of the width of the window. The controls with a defined width are aligned in the centre of the column, which is why you're getting white-space around them.
The obvious option would be to use a standard Grid . This would require adding column definitions, and setting the Grid.Column attached property on each child control.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle Fill="Blue" Grid.Column="0" />
<Rectangle Fill="Lime" Width="20" Grid.Column="1" />
<Rectangle Fill="Red" Grid.Column="2" />
<Rectangle Fill="Yellow" Width="20" Grid.Column="3" />
</Grid>
Another alternative would be to combine the UniformGrid with a DockPanel :
<UniformGrid Columns="2">
<DockPanel>
<Rectangle Fill="Lime" Width="20" DockPanel.Dock="Right" />
<Rectangle Fill="Blue" />
</DockPanel>
<DockPanel>
<Rectangle Fill="Yellow" Width="20" DockPanel.Dock="Right" />
<Rectangle Fill="Red" />
</DockPanel>
</UniformGrid>
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Of course a standard Grid is the obvious solution.
Thank you for showing me!
The UniFormGrid combined with a DockPanel was a neat solution as well.
|
|
|
|
|
I have a binding problem with my hyperlink context menu. The link shows fine and clicking it works.
The context menu shows up, but clicking on that does nothing. I don't get any BindingExpression errors.
<HierarchicalDataTemplate DataType="{x:Type entities:NavigationGroupEntity}"
ItemsSource="{Binding NavigationItems}">
<pre>
<Grid>
<TextBlock>
<Hyperlink Style="{StaticResource HyperlinkStyle}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.NavHeaderLinkClickedCommand}"
CommandParameter="{Binding}">>
<TextBlock Text="{Binding Caption}"/>
<Hyperlink.ContextMenu>
<ContextMenu>
<MenuItem Header="Open"
Command="{Binding OpenItemCommand}"
CommandParameter="{Binding}"/>
</ContextMenu>
</Hyperlink.ContextMenu>
</Hyperlink>
</TextBlock>
</Grid>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
Ya I already saw that.
From what I can see, the problem has something to do with the facts that the hyperlink isn't part of the visual tree.
I spent a while trying to get this to work. This HAS to be possible.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
I have a HierarchicalDataTemplate for a TreeViewItem that creates Hyperlinks for each item. When the mouse is over the treeview item, I want to show a button to the right.
The code below uses a trigger to show the button when the mouse is over the item, but when I move the mouse to the right off the link portion, the button dissapears.
What's the right way to create this trigger so that I can click on the button?
<HierarchicalDataTemplate DataType="{x:Type entities:NavigationGroupEntity}"
ItemsSource="{Binding NavigationItems}">
<pre>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
HorizontalAlignment="Stretch">
<Hyperlink Style="{StaticResource HyperlinkStyle}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.NavHeaderLinkClickedCommand}"
CommandParameter="{Binding}">>
<TextBlock Text="{Binding Caption}"/>
</Hyperlink>
</TextBlock>
<Button Grid.Column="1"
x:Name="button"
Visibility="Hidden"
VerticalAlignment="Center"
Padding="0"
Height="24"
Width="24"
Style="{StaticResource flatButtonStyle}">
<TextBlock Text="+"
Foreground="SteelBlue"
VerticalAlignment="Top"
FontSize="18"/>
</Button>
</Grid>
<HierarchicalDataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="button" Property="Visibility" Value="Visible"/>
</Trigger>
</HierarchicalDataTemplate.Triggers>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
A "link" that's not a link, but "shows" a button.
Why don't user's just click on the link to do whatever this button is supposed to do?
Or create a "hierarchy of buttons" (instead of "links" to a button).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Gerry Schmitz wrote: Why don't user's just click on the link to do whatever this button is supposed to do?
The link opens a record in a view. For example, this listbox of links opens Projects, with the Project name being the link.
The button to the right will add the Project to another list called Quick Actions.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I don't see the point of a "link" (misuse).
It sounds like a "parent-child" relationship where the "selection" in the Parent listbox invokes a "subordinate" action.
Nothing about "linking".
Sounds like the "new view" (with the project) should have the "button" for the Quick Action.
"Disappearing" and "appearing" things is never a good idea; enabling / disabling is better (IMO). Less (re)orientating for the user.
I think a "context menu" right-click off your original selection is probably the most conventional / appreciated.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
|
Hi Kevin,
I know I am a little late to the party, haven't been visiting as much as I used to. However, I wasn't sure if you ever fixed your problem.
If I understand what your original question was, it would be that as you were on the treeviewitem the link would show but as soon as you moved to click on the link, the link would disappear.
I have created something similar in a project of mine. I think your trigger is set up correctly, however, I think it is your actual template that might be causing the problem.
I created a Grid much like yours, but instead of breaking it down in to columns I used a stack panel and set the orientation to horizontal. I think this makes the entire item one control instead of seeing two different entities inside of a grid. This allows for me to scroll over to my buttons without losing the trigger of the IsMouseOver.
as it stands
<HierarchicalDataTemplate>
<Grid>
<StackPanel Oreintation="Horizontal">
<TextBlock>
<MyButtonControl x:Name=Buttons Visibility="Hidden">
</StackPanel>
</Grid>
<HierarchicalDataTemplate.Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Buttons" Property="Visibility" Value="Visible"/>
</Trigger>
</HierarchicalDataTemplate.Trigger>
<HierarchicalDataTemplate>
As I pointed out we have set up the trigger the same, but my TreeviewItem.ItemTemplate was a little different than yours and this seems to work for me nicely. Hope it helps! Again, I know I'm a month late, but if this didn't help you, maybe it helps someone. Cheers.
|
|
|
|
|
I have a ScrollViewer with an ItemsSource that holds a user control. I need to know what the top visible item is in the scrollviewer at any given time, and I want my ViewModel to be able to react when the top item visible changes. I think that there is no built in functionality to do this, so perhaps I need to generate mouse down events in an attempt to select the topmost item, though I'd rather not have to do this.
here is the xaml for the top level stuff:
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" ScrollChanged="ScrollViewer_ScrollChanged">
<ItemsControl x:Name="DivisionItems" ItemsSource="{Binding oObsByDiv}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<uc:ucObservationsHeader/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
The ObservationHeader user control maps to a category for each set of observations, and is this:
<UserControl x:Class="MOATools.Views.ucObservationsHeader"
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:uc="clr-namespace:MOATools.Views"
mc:Ignorable="d" d:DesignHeight="115" d:DesignWidth="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="300*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="100*"/>
</Grid.RowDefinitions>
<TextBox x:Name="divNum" Text="{Binding DivNum, Mode=OneWay}" Grid.Column="0" Grid.Row="0" Margin="0,3,0,0"/>
<TextBox x:Name="divName" Text="{Binding DivName, Mode=OneWay}" Grid.Column="1" Grid.Row="0" Margin="0,3,0,0"/>
<ItemsControl ItemsSource="{Binding lObs}" Grid.Row="1" Grid.Column="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<uc:ucObservationsView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
Each observation header then has a list of observations mapped to the ObservationsView:
<UserControl x:Class="MOATools.Views.ucObservationsView"
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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d" d:DesignHeight="75" d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="25*"/>
<RowDefinition Height="25*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".2*"/>
<ColumnDefinition Width=".4*"/>
<ColumnDefinition Width=".4*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtDivObs" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding obsFullNum, Mode=OneWay}" Grid.Column="0" Grid.Row="0"/>
<Label x:Name="lblOpenDate" HorizontalAlignment="Left" Content="Open " Grid.Column="1" Grid.Row="0"/>
<DatePicker x:Name="dtOpen" HorizontalAlignment="Right" SelectedDate="{Binding Opendate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="0"/>
<Label x:Name="lblCLoseDate" HorizontalAlignment="Left" Content="Close " Grid.Column="2" Grid.Row="0"/>
<DatePicker x:Name="txtCloseDate" HorizontalAlignment="Right" SelectedDate="{Binding Closedate}" Grid.Column="2" Grid.Row="0"/>
<TextBox x:Name="txtDescription" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding Description}" VerticalAlignment="Top" Grid.ColumnSpan="3" Grid.Row="1"/>
<TextBox x:Name="txtImagePath" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding ImagePath}" Grid.Row="2" Grid.ColumnSpan="3">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding DataContext.PreviewImage, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
</UserControl>
What I want is that as the user scrolls through the categories and observations, each time a new observation category hits the top of the window then a combo box that is bound to a list of the categories to be set to that category. This will make it easy for the user to enter a new observation by defaulting to the current category that they see in the window. I don't want them to have to first select the header or an observation because extra clicks like that are just bad design. But I can't find any way for the view to know anything about the items that are scrolled into view. The scroll viewer can give me a vertical scroll position, but it's not really correlated to the actual parent and child items in the datastructure. Is this possible?
|
|
|
|
|
The convention is that you sync to the "selected item"; not any old item that "scrolls into view".
Without a "selected item", the user is guessing in terms of what is related to what (and so are you).
And simply "scrolling a list" (using the "thumb" for example) should NOT change the "selected item".
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Thanks Gerry, I do understand that using selected item is the convention, and I do that as well. This issue is a different case, and I have found a solution that works which is to use the Scroll event from the scroll viewer and test for the item containers to see if the render in the visible portion or not. This might be a convenience that only pertains to this use case, but it's interesting that WPF is flexible enough to allow for these things to work even if they aren't intended or preferred.
|
|
|
|