Search code examples
wpftreeviewviewmodelivalueconverter

How to pass a value to iValueConverter


I was trying to solve the following problem (and finally succeeded but probably not in the best way). This is how I tried first:

I am showing a treeview with directories and a checkbox with this WPF code:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

<Grid>
    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
        <StackPanel.Resources>
            <!-- This Style is applied to all TextBlock elements in the command strip area. -->
            <Style TargetType="TextBlock">
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="Foreground" Value="#EE000000" />
            </Style>
            <local:ColorConverter x:Key="XcolorConverter" />
        </StackPanel.Resources>
        <TreeView ItemsSource="{Binding View}">
        <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type local:Folder}" ItemsSource="{Binding SubFolders}">
                    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                        <TextBlock Background="{Binding Path=., Converter={StaticResource XcolorConverter}}" Text="{Binding Name}"/>                            
                        <CheckBox Focusable="False" IsChecked="{Binding IsChecked}"  VerticalAlignment="Center"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
    </TreeView>
    </StackPanel>
</Grid>

What I would need to know in the ColorConverter method Convert, below, is the full directory name to color directories which meet a specific criterium. Parameter "value" is a string with the value (MyNameSpace).Folder. If I inspect "value" in the debugger, I also see "Name" which is the directory name (without the preceding full path) displayed in the Treeview's textbox. However, I can not access value:Name within the program (error CS1061: 'object' does not contain a definition for 'Name', I don't understand why I can see it in the debugger but not access it) nor would it help me as I need the full directory path. Within the ViewModel class/code there's a ForEach assigning the directory names to the ObservableCollection Folder. The object parameter is empty; I know I could add ConverterParameter= in the xaml but don't know how to access the actual displayed directory from within that xaml.

How should I change the WPF so my colorConverter.Convert method can access the (full) directory it is displaying at that moment?

    public ICollectionView View { get => cvs.View; }
    private CollectionViewSource cvs = new CollectionViewSource();
    private ObservableCollection<Folder> col = new ObservableCollection<Folder>();

public class Folder { public string Name { get; set; } public ObservableCollection SubFolders { get; set; } = new ObservableCollection(); }

public partial class ColorConverter : IValueConverter
    {
        private static int count;
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        { // Set color based upon directory, something like if paramater.(directory=c:\\temp")...
            return Brushes.Green;
        }
     }   

Solution

  • If I understood correctly what you need:

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Validating the type of incoming value
        if (value is Folder folder)
        {
            // Here we work with the folder variable
            string name = folder.Name;
    
            // Set color based upon directory, something like if paramater.(directory=c:\\temp")...
            return Brushes.Green;
        }
        // If the received value is not of the Folder type,
        // then the converter returns an undefined value.
        return DependencyProperty.UnsetValue;
    }