【问题标题】:How can I get data from user Control in MainWindow如何从 MainWindow 中的用户控件获取数据
【发布时间】:2015-03-03 08:50:08
【问题描述】:

我有用户控件,它有两个控件 标签文本块

   <UserControl x:Class=MyClass....
                 d:DesignHeight="300" d:DesignWidth="300" x:Name="MyUsrCtrl">
      <StackPanel>
           <Label Content={Binding MyLabelContent} x:Name="MyLabel"...../>
           <TextBlock Content={Binding MyTextBlockContent} x:Name="MyTextBlock"...../>
     </StackPanel>

  </UserControl> 

在我的 MainWindow 中,我有一个 ListBox,其 ItemSource 绑定到此用户控件的集合

 <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    <Grid>
        <ListBox x:Name="myListBox" Grid.Row="0"
             ItemsSource="{Binding Path=_myControl}"> // collection of user controls
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <local:MyUserControl x:Name="myUserControl" />
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>

    </ListBox>

在列表框中选择任何项目时,如何获取TextblockLabel 的值?

【问题讨论】:

  • 使用 ListBox 的 SelectedItem 属性。
  • 当我点击文本块上的某处时它不起作用
  • 试试看这个帖子:[用户控件与主窗口的关系][1][1]:stackoverflow.com/questions/16897188/…
  • ItemsSource 不应绑定到控件集合。相反,应该有一个数据项的集合(即视图模型中的一个类)。
  • MSDN 上的Data Templating Overview 文章是一个很好的起点。您只需创建一个带有标签和文本块的 DataTemplate,而不是 UserControl。 DataTemplate 当然也可能包含您的 UserControl,但这不是绝对必要的。

标签: c# wpf mvvm


【解决方案1】:

这对我有用:

  • 创建了一个名为 MyControl 的模型,它“代表”了 MyUserControl 中的数据
  • 创建了一个“表示”列表框中数据的 ObservableCollection
  • 这样你也可以删除所有的x:Name
  • 从 UI 中分离数据

MainWindow.xaml

   <ListBox x:Name="MyListBox" Grid.Row="0"
         ItemsSource="{Binding MyControls}"
             SelectionChanged="MyListBox_OnSelectionChanged"
             SelectionMode="Single"
             >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <local:MyUserControl></local:MyUserControl>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>

    </ListBox>

MainWindow.cs

   public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

        MyControls = new ObservableCollection<MyControl>();
        var a = new MyControl { MyLabelContent = "label content 1", MyTextBlockContent = "Text content 1" };
        var b = new MyControl { MyLabelContent = "label content 2", MyTextBlockContent = "Text content 2" };

        MyControls.Add(a);
        MyControls.Add(b);

    }


    private void MyListBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listBox = sender as ListBox;
        if (listBox != null)
        {
            var selectedItem = listBox.SelectedItems[0] as MyControl;

            var textBlockContent = selectedItem.MyTextBlockContent; //text in textblock
            var labelContent = selectedItem.MyLabelContent; //text in label

        }
    }


    private ObservableCollection<MyControl> _myControls;


    public ObservableCollection<MyControl> MyControls
    {
        get { return _myControls; }
        set
        {
            _myControls = value;
            NotifyPropertyChanged("MyControls");
        }
    }


    #region PropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }


    #endregion


}

MyUserControl.XAML

   <StackPanel>
        <Label Content="{Binding MyLabelContent}" />
      <TextBlock Text="{Binding MyTextBlockContent}" />
 </StackPanel>

MyControl.cs

 public class MyControl
{
    public string MyLabelContent { get; set; }
    public string MyTextBlockContent { get; set; }

}

希望这对你有用:)

这是一个工作示例的链接: https://drive.google.com/file/d/0B8O-XH0V_o1hNXprX2c0S0xJUFU/view?usp=sharing

【讨论】:

  • 次要但常见的约定是在 VM 类名称中添加“ViewModel”后缀。即MyControlViewModel
  • 好点,有点扔了。欢迎您编辑 :) @GazTheDestroyer
【解决方案2】:

如果你想从选中的项目中获取 TextBlock,你可以这样做:

 var selectedUserControl = myListBox.SelectedItem as MyUserControl;
 TextBlock textBlock = selectedUserControl.MyTextBlock;

希望有所帮助!

【讨论】:

  • 这需要公开 MyTextBlock 字段(由 x:Name 声明生成)。默认情况下它是私有的。
  • @Clemens 是的,你是对的,默认情况下元素可访问性是私有的,但我对此进行了测试,我可以访问该元素
猜你喜欢
  • 2019-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多