UserControl Data Binding retrieve value

2019-09-13 05:36发布

问题:

with this simple code:

MainWindows:

using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace itemcontrole_lesson
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
  public class TodoItem
        {
            public string Username { get; set; }
            public int Completion { get; set; }
        }


    public partial class MainWindow : Window
    {  
        List<TodoItem> items = new List<TodoItem>();
        public MainWindow()
        {
            InitializeComponent();

            items.Add(new TodoItem() { Username = "Eric", Completion = 45 });
            items.Add(new TodoItem() { Username = "Maxwell", Completion = 80 });
            items.Add(new TodoItem() { Username = "Sarah", Completion = 60 });
           icTodoList.ItemsSource = items;
        }
    }

Mainwindows XAML:

<Window x:Class="itemcontrole_lesson.MainWindow"
        xmlns:local="clr-namespace:itemcontrole_lesson"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ItemsControl x:Name="icTodoList">

            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type local:UserControl1}">

                    <local:UserControl1 />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

then a simple UserControle:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace itemcontrole_lesson
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
            //String  CurentUserName = ????????
            //Int  Progress = ????????
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ///hows to remove the user from items in main windows??
        }
    }
}

UserControle XAML

<UserControl x:Class="itemcontrole_lesson.UserControl1"
             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="54.181" Width="399.331">
    <Grid Margin="0,0,-155,0">
        <Label Content="{Binding Username}" HorizontalAlignment="Left" Margin="23,23,0,0" VerticalAlignment="Top"/>
        <Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0" VerticalAlignment="Top" Width="119" Click="Button_Click"/>
        <ProgressBar HorizontalAlignment="Left" Value="{Binding Completion}" Height="10" Margin="204,23,0,0" VerticalAlignment="Top" Width="154"/>
    </Grid>
</UserControl>

Pressing F5 everything will bind ok if you test. But! how I'm supposed to retrieve my variable value in my usercontrole code? see where I put comment in UC. 1- I need at least to find a way to remove this control from UI and from Items list?. 2-I'd like access username in my control and set it into a var any suggestion?

回答1:

Solution 1:

Use Tag property of button like below:

<Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0" 
            VerticalAlignment="Top" Width="119" Click="Button_Click" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />

Event handler:

private void Button_Click(object sender, RoutedEventArgs e)
    {
         var button = sender as Button;
         List<object> list = (button.Tag as ItemsControl).ItemsSource.OfType<TodoItem>().ToList<object>();
        list.Remove(button.DataContext);
        (button.Tag as ItemsControl).ItemsSource = list;
    }

Solution 2:

More elegant solution:

Create this Style in your MainWindow:

<Window.Resources>
    <Style TargetType="Button">
        <EventSetter Event="Click" Handler="Button_Click"/>
    </Style>
</Window.Resources>

So now the Handler of any Button Click event is in the MainWindow.xaml.cs.

Then change handler definition like below:

private void Button_Click(object sender, RoutedEventArgs e)
    {
        var button = sender as Button;
        items.Remove(button.DataContext as TodoItem);
        icTodoList.ItemsSource = null;
        icTodoList.ItemsSource = items;            
    }