0

I have TreeView and TreeViewItems. TreeViewItems contain Tags either "type", "class", "subclass", or a Guid in the form "0202-7252-4a4a...".

What I am currently doing is that I am displaying the Tag and Header of those TreeViewItems on the screen with the following code.

(Please do not consider how I am creating the TreeViewItems, it is not relevant for my case)

<TreeView x:Name="treeView"/>

<TextBlock>
    <Run text="{Binding ElementName=treeView, Path=SelectedItem.Tag}"/>
    <Run text="{Binding ElementName=treeView, Path=SelectedItem.Header}"/>
</TextBlock>

I don't want to write the Tag of a TreeViewItem whose tag is Guid because it doesn't seem pretty in the screen. I want to add an if condition to this code as follows:

if (TreeViewItem.Tag == "type" or "class" or "subclass")
    write tag and header to screen
else do nothing

OR

if (TreeViewItem.Tag is Guid) then do nothing
thatguy
  • 21,059
  • 6
  • 30
  • 40
  • Please take a look at the CollectionViewSource class. It will allow you to include a Filter on the elements within your hierarchical data structure, returning a Boolean value that reports whether the item should be shown. Examples here: https://stackoverflow.com/questions/20888619/proper-way-to-use-collectionviewsource-in-viewmodel – LordWilmore Feb 07 '22 at 08:18
  • hi you should visit this site, your answer is here https://stackoverflow.com/questions/273141/regex-for-numbers-only – faragh47 Feb 07 '22 at 08:54
  • Consider using a MultiBinding with a multi-value Converter. – Clemens Feb 07 '22 at 09:10

2 Answers2

0

You could create a converter that returns a Visibility for certain keywords. In XAML you can pass a list of keywords in XAML that will return Visibility.Visible, otherwise it will be Visibility.Hidden.

public class KeywordToVisibilityConverter : IValueConverter
{
   public List<string> Keywords { get; }

   public KeywordToVisibilityConverter()
   {
      Keywords = new List<string>();
   }

   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      return value is string keyword
         ? Keywords.Contains(keyword) ? Visibility.Visible : Visibility.Hidden
         : Visibility.Hidden;
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

Create an instance of the converter in a resource dictionary in scope, e.g. TreeView.Resources.

<TreeView.Resources>
   <local:KeywordToVisibilityConverter x:Key="KeywordToVisibilityConverter">
      <local:KeywordToVisibilityConverter.Keywords>
         <system:String>type</system:String>
         <system:String>class</system:String>
         <system:String>subclass</system:String>
      </local:KeywordToVisibilityConverter.Keywords>
   </local:KeywordToVisibilityConverter>
</TreeView.Resources>

Do not forget to add the XML namespace for system.

  • xmlns:system="clr-namespace:System;assembly=System.Runtime" for .NET Core
  • xmlns:system="clr-namespace:System;assembly=mscorlib" for .NET Framework

Then, use the converter to set the visibility of the TextBlock depending on Tag.

<TextBlock Visibility="{Binding SelectedItem.Tag, ElementName=treeView, Converter={StaticResource KeywordToVisibilityConverter}}">
   <Run Text="{Binding ElementName=treeView, Path=SelectedItem.Tag}"/>
   <Run Text="{Binding ElementName=treeView, Path=SelectedItem.Header}"/>
</TextBlock>

A converter for your second case is fairly easier, as it just checks the type (no namespace or list needed).

public class IsGuidToVisibilityConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      return value is Guid ? Visibility.Hidden : Visibility.Visible;
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

As before, create an instance in XAML and use it to bind the Visibility of TextBlock.


As a note, if you wanted to bind the allowed keywords, too, the you would have to create a IMultiValueConverter used in a MultiBinding in XAML. If you want the TextBlock not only hidden, but removed leaving empty space, replace Hidden with Collapsed. Finally, to state the obvious: Be careful, the approaches are not equivalent. Depending on the possible Tag values they may lead to different results.

thatguy
  • 21,059
  • 6
  • 30
  • 40
0

You can use a Converter for this type of issues. With this methodology we can manipulate the TreeViewItemsin such a way that "GUID" is not displayed in UI at the end.

1. Create a new Converter Class

During the generation of TreeViewItems it will hit this converter.

This class is implementing the IValueConverter interface. The Convert method will be used from XAML to convert the respectively bound object at runtime.

In the Convert Method you can add your specified if conditions you mentioned in your question.

Something like this should work:

public class MyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            //Some condition to extract only "type", "class" or "subclass" from the tag property of TreeViewItem
            if (value.GetType() == typeof(Guid))
                return "";
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

2. Add the Converter to the respectively tag

First of all you need to add the namespace of the Converter Class to the XAML as a resource.

Read more about this here https://stackoverflow.com/a/34351786/17604152

Adding converter as a resource:

<Window x:Class="MyNameSpace.MainWindow"
....
        xmlns:conv="clr-namespace:MyNameSpace.Converter"
>
......
......

    <Window.Resources>          
       <conv:MyConverter x:Key="myConverter"/>
    </Window.Resources>

Then you can

<TextBlock>
    <Run text="{Binding ElementName=treeView, Path=SelectedItem.Tag, Converter={conv:myConverter}}"/>
    <Run text="{Binding ElementName=treeView, Path=SelectedItem.Header}"/>
</TextBlock>
enesimam
  • 106
  • 3