WPF绑定ObservableCollection <string>到ItemsControl不工作</string>

时间:2012-09-07 12:00:16

标签: c# wpf data-binding observablecollection itemscontrol

我有一些字符串属性需要解析内容,并显示在单独的控件中。假设有空格分隔的电子邮件和网址。显示电子邮件工作正常,但网址没有。这是代码:

XAML文件:

<ScrollViewer Grid.Row="0" Grid.Column="5" >
        <StackPanel Orientation="Vertical">
            <TextBox Name="EmailTextBox"
                     Text="{Binding ElementName=candidatePersonalDataViewControl, Mode=OneWay, Path=Candidate.Email, Converter={StaticResource emailConverter}}"/>

            <ItemsControl ItemsSource="{Binding ElementName=candidatePersonalDataViewControl, Mode=OneWay, Path=UrlsProperty}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock
                            Margin="0,0,0,0"
                            Padding="5,2,5,2"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Top">
                            <Hyperlink NavigateUri="{Binding Path=/}" 
                                       Click="EmailAsWWW_Click">
                                <Run Text="{Binding Path=/}" />
                            </Hyperlink>
                        </TextBlock>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel Orientation="Vertical" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </StackPanel>
    </ScrollViewer>

C#文件:

    private static readonly DependencyProperty CandidateProperty = DependencyProperty.Register("Candidate", typeof(Candidate), typeof(CandidatePersonalDataViewControl));
    public Candidate Candidate
    {
        get { return (Candidate)GetValue(CandidateProperty); }
        set { SetValue(CandidateProperty, value); }
    }

    public CandidatePersonalDataViewControl()
    {
        InitializeComponent();
        this.DataContext = this;
        UrlsProperty = new ObservableCollection<string>();
    }

    public ObservableCollection<string> UrlsProperty
    {
        get;
        private set;
    }

    private void Grid_LayoutUpdated(object sender, EventArgs e)
    {
        if (Candidate == null)
            return;
        if (Candidate.Email == null)
            return;


        EmailPropertyToEmailsConverter emailConverter = new EmailPropertyToEmailsConverter();
        bool emails = (emailConverter.Convert(Candidate.Email, typeof(string), null, null) as string) != null;
        this.EmailTextBox.Visibility = emails ? Visibility.Visible : Visibility.Collapsed;

        EmailPropertyToUrlListConverter urlConverter = new EmailPropertyToUrlListConverter();
        IList<string> urls = urlConverter.Convert(Candidate.Email, typeof(string), null, null) as IList<string>;
        UrlsProperty.Clear();
        if (urls != null)
            foreach (string url in urls)
                UrlsProperty.Add(url);
    }

我调试了Grid_LayoutUpdated,它运行正常。只要需要它就会被触发,而UrlsCollection包含所需的数据。正如我所说,EmailTextBox显示数据,但ItemsControl一直是空的。更重要的是,从超链接绑定中删除“Path = /”会引发XAML Parse异常。我的想法已经用完...... 我已经阅读了一些主题,但没有一个是有帮助的

wpf ItemsControl binding problem

WPF Binding Path=/ not working?

WPF - bind a listbox to a list<string> - what am I doing wrong?

How do you bind ObservableCollections to ItemsSource?

3 个答案:

答案 0 :(得分:3)

Path=/绑定当前项目的集合 而非当前正在模板化的项目,通常是当前项目是被选中的那个(见IsSynchronizedWithCurrentItem)。您的DataContext是字符串而不是集合,因此尝试通过/绑定到当前项目将失败(请参阅binding errors)。

要绑定到当前正在模板化的项目,您需要直接绑定到DataContext,这可以通过{Binding}{Binding .} / {来完成{1}}(如果属性需要{Binding Path=.}选择后者之一)。

答案 1 :(得分:1)

您的超链接控件需要NavigateUri属性的Uri,但您只需绑定到字符串。

实现目标的一种方法是使用NavigateUri Binding的转换器

<Hyperlink NavigateUri="{Binding Path=., Converter={StaticResource YourStringToUriConverterGoesHere}}" Click="EmailAsWWW_Click">
  <Run Text="{Binding}" />
</Hyperlink>

另一种方式是更改集合

public ObservableCollection<MyUrlWrapper> UrlsProperty
{
    get;
    private set;
}

public class MyUrlWrapper
{
    public string Url {get;set;}
    public Uri MyUri {get{return new Uri(this.Url);}}
}

<Hyperlink NavigateUri="{Binding Path=MyUri}" Click="EmailAsWWW_Click">
  <Run Text="{Binding Path=Url}" />
</Hyperlink>

答案 2 :(得分:0)

尝试:

<Hyperlink NavigateUri="{Binding}" Click="EmailAsWWW_Click">
    <Run Text="{Binding}" />
</Hyperlink>