The Selection Issues
button opens a dialog that contains just the issues for the selected
page or shapes. If there are multiple issues on the page, or on a shape,
then they are grouped together for clarity.
I have already expressed a preference to use WPF where possible.
However, the VSTO template, which is a Windows Forms project, hides the
WPF window item type from selection if you try to add one. You are only
offered the User Control (WPF)
to add in the WPF category of installed templates. Fortunately, you can
select this option and then make some simple changes to the code to
turn a User Control (WPF) into a Window (WPF). In this case, I added a new UserControl (WPF) named WindowIssues. I then edited the XAML of the WindowIssues.xaml file.
From:
<UserControl x:Class="ValidationExplorer.UI.WindowIssues"
…etc
</UserControl>
To:
<Window x:Class="ValidationExplorer.UI.WindowIssues"
…etc
</Window>
Similarly, I edited the WindowIssues.xaml.cs and changed the following line:
From:
public partial class WindowIssues : UserControl
To:
public partial class WindowIssues : Window
The WindowIssues class is now a true WPF window that can be edited to display the issues for the selection.
The ThisAddin class has a method to open the selected issues dialog.
public void OnActionOpenSelectionIssues()
{
ViewModel.VEDocument document = this.documents[Globals.ThisAddIn.Application.ActiveDocument.ID];
if (document != null)
{
// this is our document so call open window
document.OpenSelectionIssues();
}
}
The OpenSelectionIssues() method is quite simple, because the list view in the WindowlIssues.xaml file is based on a filtered view of the current document VEIssues observable collection.
public void OpenSelectionIssues()
{
Globals.ThisAddIn.VEApp.SelectedVEDocument = this;
UI.WindowIssues frm = new UI.WindowIssues();
frm.ShowDialog();
}
The WindowIssues.xaml file defines the list view, complete with its grouping.
First, you need to include an extra namespace:
xmlns:dat="clr-namespace:System.Windows.Data; assembly=PresentationFramework"
Next, you can use this namespaces to define the CollectionViewSource grouping, as follows:
<CollectionViewSource Source="{Binding Path=VEIssues}" x:Key="listingDataView"
Filter="CollectionViewSource_Filter">
<CollectionViewSource.GroupDescriptions>
<dat:PropertyGroupDescription PropertyName="TargetName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
You can then reference this collection view source in the ListView.
<ListView Name="ListViewMain"
SelectionChanged="ListViewMain_SelectionChanged"
ItemsSource="{Binding Source={StaticResource ResourceKey=listingDataView}}">
Next, you can define the ListView.GroupStyle binding to the Name of the group:
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="300"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
Lastly, the ListView.View can be defined binding to the properties of the VEIssue objects:
<ListView.View>
<GridView>
<GridViewColumn Width="120" Header="Category" DisplayMemberBinding="{Binding Path=Rule.Category}"/>
<GridViewColumn Width="240" Header="Rule" DisplayMemberBinding="{Binding Path=Rule.Description}"/>
<GridViewColumn Width="120" Header="NameU" DisplayMemberBinding="{Binding Path=Rule.NameU}"/>
<GridViewColumn Width="60" Header="IsIgnored" DisplayMemberBinding="{Binding Path=IsIgnored}"/>
<GridViewColumn Width="120" Header="RuleSet Name" DisplayMemberBinding="{Binding Path=Rule.RuleSet.Name}"/>
<GridViewColumn Width="240" Header="RuleSet Description" DisplayMemberBinding="{Binding Path=Rule.RuleSet.Description}"/>
</GridView>
</ListView.View>
The constructor in the code sets the DataContext for UserControlIssues:
public WindowIssues()
{
InitializeComponent();
if (Globals.ThisAddIn.VEApp.SelectedVEDocument != null)
{
this.DataContext = Globals.ThisAddIn.VEApp.SelectedVEDocument;
}
}
The CollectionViewSource_Filter() method is called in the XAML definition of the CollectionViewSource and is defined as follows:
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
ViewModel.VEIssue issue = e.Item as ViewModel.VEIssue;
bool ignore = (issue.IsIgnored == true
&& Globals.ThisAddIn.Application.ActiveDocument.Validation. ShowIgnoredIssues == false);
if (ignore == true) {e.Accepted = false; return; }
issuesfor current selection, displayingif (Globals.ThisAddIn.Application.ActiveWindow.Selection.Count == 0)
{
//Check for the active page
if (issue.TargetPage == Globals.ThisAddIn.Application.ActivePage
&& issue.TargetShape == null)
e.Accepted = true;
else e.Accepted = false;
}
else
{
//Check for the Target Shape in the active selection
foreach (Visio.Shape shp in Globals.ThisAddIn.Application.ActiveWindow.Selection)
{
if (issue.TargetPage == Globals.ThisAddIn.Application.ActivePage
&& issue.TargetShape != null)
{
if (shp == issue.TargetShape)
{
e.Accepted = true;
break;
}
else { e.Accepted = false; }
}
else e.Accepted = false;
}
}
}