3

I am trying to bind a list of objects to a list of HyperLinks that are comma-separated, and clickable.

I can do it if it's only one of them per cell, but I don't know how to bind a collection per cell.

Something like this in a single GridViewColumn cell:

Effect01, Effect02, Effect02, Shader01. Shader02

where clicking any of them will call the binded object's Execute method.

Each element is:

public class EffectLink : IExecutable
{
    public string Name {get; set;}
    public void Execute ();
}

as enforced by IExecutable.

I do it this way because the behaviour of Execute will depend on whether it's a shader, an effect, etc.

Any ideas?

EDIT:

I found that I could do this:

<TextBlock>
    <Hyperlink>Effect01</Hyperlink>
    <Hyperlink>Effect02</Hyperlink>
</TextBlock>

So this shows 2 space-separate hyperlinks in a single cell.

Also this question might be related, but it shows how do it in code, not xaml: Nested TextBlocks and Hyperlinks, How do you replicate this XAML in C#?

Community
  • 1
  • 1
Joan Venge
  • 315,713
  • 212
  • 479
  • 689

1 Answers1

4

put an ItemsControl in your GridViewColumn.CellTemplate

    <GridViewColumn >
        <GridViewColumn.CellTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>

                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock x:Name="commaTextBlock" Text=", " />
                                <TextBlock><Hyperlink><Run Text="{Binding Path=Name}" /></Hyperlink></TextBlock>
                            </StackPanel>

                            <DataTemplate.Triggers>
                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
                                    <Setter Property="Visibility" TargetName="commaTextBlock" Value="Collapsed"/>
                                </DataTrigger>
                            </DataTemplate.Triggers>
                        </DataTemplate>

                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </DataTemplate>
        </GridViewColumn.CellTemplate>
    </GridViewColumn>
kenwarner
  • 28,650
  • 28
  • 130
  • 173
  • Thanks, one thing that's different is the Effects collection is inside the ObservableCollection so Effects is a property for each GraphNode. Do you know how I can bind it to this collection? Currently ListView ItemsSource is set to ObservableCollection, so these hyperlinks should be generated from each GraphNode.Effects collection. Does it make sense? – Joan Venge Mar 25 '11 at 17:06
  • instead of `` you'd have `` – kenwarner Mar 25 '11 at 17:35
  • also, you can use http://stackoverflow.com/questions/2511227/how-can-a-separator-be-added-between-items-in-an-itemscontrol to properly display commas rather than the spaces my XAML has – kenwarner Mar 25 '11 at 17:38
  • @qntmfred: Thanks a lot, it works great. Didn't take any fiddling to get it working. Also I was experimenting with your xaml to add commas that aren't hyper links, so just like yours but with ", " but replacing `Run Text=" "` with `Run Text=", "` made the link part of the hyperlink. I understand why but do you know if it's possible to have the commas as non-clickable texts? Thanks again. – Joan Venge Mar 25 '11 at 17:45
  • Just saw your new post, like you read my mind :O Will check out your link now. – Joan Venge Mar 25 '11 at 17:46
  • I tried what's shown in your link and it works, but there is a space after the item name, so it looks like this: "effect01" ,"effect02" , etc. I used this xaml: ` ` Btw I left the `Run Text=""` for flexibility if I needed to change in the future. But still it's empty string. – Joan Venge Mar 25 '11 at 17:49
  • Also if that formatting can't be done, it's not a big deal. Although I was wondering if you could also show me if it's possible to run a method inside the type each hyperlink is binded to when the link is clicked? I think I can do it if it has to be done on the code side, but if it would be specified on the xaml side, I think that would be better because I wouldn't have to try to find which link is clicked when the event is called, etc. – Joan Venge Mar 25 '11 at 18:06
  • 1
    updated the xaml for the commas and the extra hyperlink padding you mentioned – kenwarner Mar 25 '11 at 18:07
  • 1
    you can bind `HyperLink.Command` to an `ICommand` on your EffectLink object which can call your Execute() method – kenwarner Mar 25 '11 at 18:19
  • Thanks qntmfred, it works great. I am binding the command to the method but it says that there is no property called Execute. Is the syntax to bind to methods different? But I don't mind restricting it IExecutable/ICommand because that's what I want. – Joan Venge Mar 25 '11 at 18:24
  • 1
    well, you probably need to make a property on EffectLink called ExecuteCommand of type ICommand, and use something like a [RelayCommand](http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030) to hook the ExecuteCommand to your Execute method, then your HyperLink binding would look like Command="{Binding Path=ExecuteCommand}" – kenwarner Mar 25 '11 at 18:34
  • Thanks qntmfred, I did it like you said and it works. But all this RelayCommand and stuff, are they not generic/common enough to be part of WPF? Or is this just another implementation of ICommand. Thanks again man, I wish I could give you more points. – Joan Venge Mar 25 '11 at 19:08