【问题标题】:How to use two user controls as Master –Details如何使用两个用户控件作为主控 - 详细信息
【发布时间】:2012-06-23 09:14:55
【问题描述】:

我现在已经创建了两个用户控件,我想将一个用作主用户控件,另一个用作详细用户控件,如下所示:

1 Parent Control
  1.1 - User Control 1 as Master Control
  1.2 - User Control 2 as Details Control

主控件有一个列表框,我在其中选择项目的名称,详细信息控件显示库存中所有可用的项目。 我在父控件中添加了 ItemId 并将其绑定到主控件和详细信息控件(两个控件都将 ItemId 作为 DP)。 当我从 Master 中选择项目时,详细信息网格不会刷新。

当我从主用户控制中选择项目时,我如何确保;详细用户控件应该显示详细信息吗?

父控件

 <Grid>
        <StackPanel Orientation="Horizontal"
                    Width="650"
                    HorizontalAlignment="Left"
                    Margin="10,10,0,0">
             <UC:ItemDetailUC ItemId="{Binding ElementName=MainWindowName,Path=ItemId,Mode=TwoWay}" />
             <UC:StockItemDetailsUC ItemId="{Binding ElementName=MainWindowName,Path=ItemId,Mode=TwoWay}"/>
        </StackPanel>
    </Grid>

.

public partial class MainWindow : Window, INotifyPropertyChanged
        {

       private int _ItemId;
            public int ItemId
            {
                get
                {
                    return _ItemId;
                }
                set
                {
                    if (_ItemId == value)
                        return;
                    _ItemId = value;
                    OnPropertyChanged("ItemId");
                }
            }

            public MainWindow()
            {
                InitializeComponent();            
                this.DataContext = this;
            }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    }

1.1 - 用户控件 1 作为主控件 - ItemDetailUC.XAML

    <UserControl x:Class="LearnWPF.ItemDetailUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             Name="ItemDetailUCName"
             d:DesignHeight="100" d:DesignWidth="350">
    <Grid Background="Aqua">
        <StackPanel Orientation="Vertical" Margin="10,10,0,0" >
            <Label Content="Master Control:" Width="350" HorizontalContentAlignment="Center"/>
            <StackPanel Orientation="Horizontal" Width="200" HorizontalAlignment="Left" Margin="10,10,0,0">
                <Label Content="Item :" Width="80"/>
                <ComboBox Name="ItemListComboBox" Width="100"
                          DisplayMemberPath="ItemName"
                          SelectedValuePath="ItemId"
                          SelectedValue="{Binding ElementName=ItemDetailUCName, Path=ItemId}" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="10,10,0,0">
                <Label Content="Available Qty :" Width="80"/>
                <TextBox Width="100" Text="{Binding ElementName=ItemListComboBox, Path=SelectedItem.AvailableQty}" />
                 <Label Content="MaxQty :" Width="60"/>
                <TextBox Width="80" Text="{Binding ElementName=ItemListComboBox, Path=SelectedItem.MaxQty}" />
           </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>

.

    public static readonly DependencyProperty ItemIdProperty = DependencyProperty.Register("ItemId", typeof(int), typeof(ItemDetailUC));
 public int ItemId
    {
        get
        {
            return (int)GetValue(ItemIdProperty);
        }
        set
        {
            SetValue(ItemIdProperty, value);
        }
    }


       public ItemDetailUC()
    {
        InitializeComponent();
        ItemListComboBox.ItemsSource = Data.GetItemList();
        this.DataContext = this;
    }

1.2 - 用户控件 2 作为细节控件

<UserControl x:Class="LearnWPF.StockItemDetailsUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="300">
    <Grid>

        <StackPanel Orientation="Vertical" Background="Aquamarine">
             <Label Content="Details Control:" Width="300" HorizontalContentAlignment="Center"/>

        <DataGrid Name="StockItemDetailsDataGrid" Background="Aquamarine"
                  AutoGenerateColumns="False">

             <DataGrid.Columns>
                <DataGridTextColumn Header="Location Name"  Binding="{Binding LocationName}"/>
                <DataGridTextColumn Header="RowNo" Binding="{Binding RowNo}" />
                 <DataGridTextColumn Header="ColumnNo" Binding="{Binding ColumnNo}" />
                 <DataGridTextColumn Header="Qty" Binding="{Binding Qty}" />               
            </DataGrid.Columns>


        </DataGrid>
</StackPanel>
    </Grid>
</UserControl>

.

        public static readonly DependencyProperty ItemIdProperty = DependencyProperty.Register("ItemId", typeof(int), typeof(StockItemDetailsUC));

        public int ItemId
        {
            get
            {
                return (int)GetValue(ItemIdProperty);
            }
            set
            {
                SetValue(ItemIdProperty, value);
            }
        }


        public StockItemDetailsUC()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(StockItemDetailsUC_Loaded);

        }

        void StockItemDetailsUC_Loaded(object sender, RoutedEventArgs e)
        {
            if (ItemId != 0)
            {
                StockItemDetailsDataGrid.ItemsSource = Data.GetItemLocaitonDetails(ItemId);
            }
            this.DataContext = this; 
        }
.

       public class ItemDetailsVO: INotifyPropertyChanged
    {
        private int _ItemId;
        public int ItemId
        {
            get
            {
                return _ItemId;
            }
            set
            {
                if (_ItemId == value)
                    return;
                _ItemId = value;
                OnPropertyChanged("ItemId");
            }
        }

        private String _ItemName;
         private int _AvailableQty;
         private int _MaxQty;
    }





   public class StockItemDetails : INotifyPropertyChanged
    {
        private int _ItemId;
        public int ItemId
        {
            get
            {
                return _ItemId;
            }
            set
            {
                if (_ItemId == value)
                    return;
                _ItemId = value;
                OnPropertyChanged("ItemId");
            }
        }

        private String _LocationName;
        private int _Qty;
        private int _RowNo;
        private int _ColumnNo;
        /..... all properties are implemented
    }

【问题讨论】:

    标签: wpf user-controls master-detail


    【解决方案1】:

    不要只使用 ItemID 作为依赖属性,而是使用项目本身。以下场景应满足您的要求:

    假设 CItem 是您的主/详细视图中的一条记录的类型。在托管您的主控件和详细控件的视图中,使用公开 List&lt;CItem&gt; 的视图模型,或者如果您要动态添加/删除项目,则使用 ObservableCollection&lt;CItem&gt; 将其设置为主控的 ItemsSource 的绑定目标列表。此外,在视图模型中创建 CItem 类型的依赖属性“SelectedObject”。在 SelectedItem 的主列表中,创建一个与“SelectedObject”属性的双向绑定。在详细信息视图中,也只需绑定到“SelectedObject”的属性,例如

    <TextBox Text="{Binding SelectedObject.MyProperty, Mode=TwoWay}" />
    

    现在,当主视图中的用户选择不同的记录时,SelectedObject 属性会得到更新,因此,该属性上的所有详细信息绑定也会得到更新。

    编辑: 因此,如果您需要额外的逻辑,请考虑在依赖项属性 ItemID 的值更改时使用回调函数。注册依赖属性时使用PropertyMetadata PropertyChangedCallback constructor。每次依赖属性的值发生变化时都会调用回调函数。在此回调函数中,您可以触发您提到的附加逻辑,用于为详细视图加载/准备项目。

    【讨论】:

    • 在我的例子中,Details Control 有一些额外的逻辑来获取不属于主记录的数据。为了更好地理解问题,我添加了代码。
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    相关资源
    最近更新 更多