【问题标题】:Binding ObservableCollection in Custom User Control在自定义用户控件中绑定 ObservableCollection
【发布时间】:2011-07-19 12:51:02
【问题描述】:

我有一个在包含自定义类的用户控件中创建的 ObservableCollection。自定义类包含一些字符串和布尔值,没什么特别的。

public class StringLineInfo : INotifyPropertyChanged
{
    private string name { set; get; }
    private Color color { set; get; }
    private bool visible { set; get; }
    private bool follow { set; get; }

    public string Name
    {
        get { return name; }
        set
        {
            name = value;
            NotifyPropertyChanged("Name");
        }
    }

    public Color Color
    {
        get { return color; }
        set
        {
            color = value;
            NotifyPropertyChanged("Color");
        }
    }

    public bool Visible
    {
        get { return visible; }
        set
        {
            visible = value;
            NotifyPropertyChanged("Visible");
        }
    }

    public bool Follow
    {
        get { return follow; }
        set
        {
            follow = value;
            NotifyPropertyChanged("Follow");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this,
                new PropertyChangedEventArgs(propertyName));
        }
    }
}

在自定义控件的 Xaml 中,我添加了自定义图例控件。在自定义图例中,我有另一个 ObservableCollection,ItemsControl 是数据绑定到的。

在legend.xaml中:

                                <!--<Image Name="imgMyImage" Grid.Column="1" Height="30" Width="30" Margin="5" Source="{Binding Name, Converter=NameToSrcConverter, ConverterParameter={StaticResource IconDictionary}}" />-->
                            <TextBlock Name="txtlineName" FontSize="12" Foreground="Black"  Text="{Binding Converter={StaticResource nameConverter}}"  Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2"/>
                        </Grid>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

在legend.xaml.cs中:

    public ObservableCollection<StringLineInfo> allLines = new ObservableCollection<StringLineInfo>();

    public Dictionary<string, string> DvrIconDictionary = new Dictionary<string, string>();
    public Legend()
    {
        InitializeComponent();
        DataContext = this;
        itmCtrol.ItemsSource = allLines;
    }

    // to set the ItemsSource
    public void setItemsSource(ObservableCollection<StringLineInfo> source)
    {
        if (itmCtrl.ItemsSource == null)
        {
            itmCtrl.ItemsSource = source;
        }
    }

在主用户控件的构造函数中,我将图例中的 ObservableCollection 设置为等于主用户控件中的 ObservableCollection。

public MainControl()
    {
        InitializeComponent();
        MapLegend.SizeChanged += new SizeChangedEventHandler(MapLegend_SizeChanged);
        MapLegend.allLines = this.allLines;
    }

即使两个 ObservableCollections 始终包含相同的数据(它们现在是同一个对象),ItemsControl 也不会更新或显示任何内容。但是,如果我稍后在代码中将 ObservableCollections 设置为相等,比如单击按钮,那么它就可以正常工作了。

按钮只是调用“setItemsSource”函数。

关于为什么我不能在启动时将它们设置为相等的任何想法?

【问题讨论】:

  • 如果发布有关您问题的代码 sn-p,您将获得更好的答案。
  • legend.xaml 中的一些相关代码似乎丢失了。您能否也通过单击“可以正常工作”的按钮发布代码?
  • @Pavel:legend.xaml.cs 中“allLines”的数据何时/何地被填充?这不在您的代码中。
  • @jwJung 数据添加到按钮点击事件中。
  • @Scott 我添加了设置 ItemsSource 的函数。该函数只需在主控件中单击按钮即可调用。

标签: c# wpf data-binding user-controls observable


【解决方案1】:

您实际上有三个对您尝试绑定的 allLines 集合的引用。

  1. 包含 MainControl 方法的类型中的 allLines。
  2. legend.xaml.cs 中的所有行。
  3. itmCtrol.ItemsSource withing legend.xaml.cs。

我假设当您最终看到数据时,第一个引用已正确填充。第二个引用使用不需要的空 ObservableCollection 进行初始化(您可以节省初始化此对象的开销)。第三个设置为与第二个相同的空集合。

您在 MainControl 方法中的代码将第二个引用设置为正确填充的集合,但不会以任何方式影响第三个引用 (itmCtrl.ItemsSource) - 它保留对空集合的引用。

我的猜测是,您在“正常工作”的按钮单击事件中使用了 legend.xaml.cs 中的以下代码。

itmCtrol.ItemsSource = allLines;

这会将 itmCtrol.ItemsSource 引用从空集合交换到正确填充的集合。

最简单的解决方案是将 allLines 字段替换为直接委托给 itmCtrol.ItemSource 属性的属性(使用 itmCtrol.ItemsSource 属性作为新属性的支持字段)。它看起来像这样。

    public ObservableCollection<StringLineInfo> AllLines
    {
        get
        {
            return (IObservableCollection<StringLineInfo>)itmCtrol.ItemsSource;
        }
        set
        {
            itmCtrol.ItemsSource = value;
        }
    }

【讨论】:

  • 正常工作的按钮在 MainControl 中并调用此函数: public void setItemsSource(ObservableCollection source);它传入原来的 allLines
  • 变量名是否正确? itmCtrol 和 itmCtrlDVRs 是一样的吗?如果是这样,我上面提供的解决方案是有效的。
  • 我明白你的意思。谢谢。
  • 没问题。很高兴我能帮上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 2012-01-07
相关资源
最近更新 更多