Связывание ObservableCollection в пользовательском элементе управления - PullRequest
0 голосов
/ 19 июля 2011

У меня есть 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.

В легенде. 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>

В легенде.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".

Есть идеи, почему я не могу установить их равными при запуске?

1 Ответ

2 голосов
/ 19 июля 2011

На самом деле у вас есть три ссылки на коллекцию allLines, к которой вы пытаетесь привязаться.

  1. allLines в типе, который содержит метод MainControl.
  2. allLines в legend.xaml.cs.
  3. itmCtrol.ItemsSource в сочетании с 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;
        }
    }
...