将模型中的数据对象集合绑定到视图中的一组控件(WPF)

时间:2011-03-24 18:12:52

标签: c# wpf data-binding collections wpf-controls

来自我的另一个WPF问题。

我目前的情况是需要将模型中的ObservableCollection<T>数据对象绑定到视图中的一组UserControl。数据对象的数量经常变化,我需要在集合发生变化时动态创建这些UserControl。当前代码如下所示:

private void viewModel_PropertyChanged( object sender, PropertyChangedEventArgs e )
{
    if( e.PropertyName.Equals( "SomeCollection" ) )
    {
        UpdateUI();
    }
}

private void UpdateUI()
{
    foreach( MyUserControl elem in _uiElements )
    {       
        elem.MouseLeftButtonDown -= elem_MouseLeftButtonDown;
        // more event handler unhooking
        _MyCanvas.Children.Remove( elem );
    }

    _uiElements.Clear();

    foreach( DataObj dataObj in ViewModel.DataObjects )
    {
        MyUserControl newElem = new MyUserControl();
        _uiElements.Add( newElem );

        fpv.MouseLeftButtonDown += fpv_MouseLeftButtonDown;
        // more event handler hookups
        newElem.DataObject = dataObj;       

        _MyCanvas.Children.Add( newElem );
        Point dest = dataObj.ScreenPoint;
        Canvas.SetLeft( newElem, dest.X );
        Canvas.SetTop( newElem, dest.Y );
    }
}        

因此,正如您所看到的,我响应(在代码中)更改的属性并动态创建一组新的UserControl。当相应的数据对象被“移动”(它包含Point属性),添加,创建或设置整个集合时,将调用此代码。问题是这可能需要(最差情况下有100多个元素)一秒钟或更长时间,这是不可接受的。控制本身很简单;只有网格和形状(椭圆)。

TLDR;


所以,我想我在问是否有人遇到过类似的情况。动态创建控件以响应集合中的更改并从UI添加/删除它们,类似于ItemsSource属性在ComboBox,ListBox,DataGrid等中的工作方式。问题是这些控件需要允许鼠标拖动和布局在Canvas中的任意位置。感谢任何帮助,提前谢谢。

2 个答案:

答案 0 :(得分:1)

为什么不使用带有ItemTemplateSelector的虚拟ItemsControl?如果控件很简单,则应该可以为它们使用datatemplates,因此无需创建用户控件。由于项目控件是虚拟化的,因此只会显示可见项目,因此应该更快。

答案 1 :(得分:0)

这正是ItemsControl的用途,但是当您需要使用Canvas并从数据中提取位置时,布局会有一些皱纹。它并不复杂,但需要一些不同的部件才能正常工作。假设您的ViewModel是DataContext:

,这是一个快速示例
<ItemsControl ItemsSource="{Binding DataObjects}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Canvas.Left" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.ScreenPoint.X}" />
            <Setter Property="Canvas.Top" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.ScreenPoint.Y}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <!-- your UserControl goes here -->
            <Ellipse Fill="Red" Width="20" Height="20" ToolTip="{Binding ScreenPoint}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

您还需要确保您的DataObjects属性是ObservableCollection,然后您就可以添加和删除对象,并在UI中自动更新已更改的项目,从而帮助您提高刷新性能问题