Проблема с привязкой данных в C # - PullRequest
3 голосов
/ 21 октября 2010

Я пытаюсь лучше понять, как работает привязка данных в .net.Я проверял эту статью и придумал следующий код:

public partial class Form1 : Form//, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler MyTextChanged;

    [System.ComponentModel.Bindable(true)]
    public string MyText
    {
        get { return textBox1.Text; }
        set 
        {
            textBox1.Text = value;
            if (MyTextChanged != null)
                MyTextChanged(this, new PropertyChangedEventArgs("MyText"));
        }
    }

    MyClass myClass { get; set; }

    public Form1()
    {
        InitializeComponent();
        myClass = new MyClass();
        Binding binding = new Binding("MyText", myClass, "Dic");
        binding.Parse += new ConvertEventHandler(binding_Parse);
        binding.Format += new ConvertEventHandler(binding_Format);
        DataBindings.Add(binding);
        myClass.AddStuff("uno", "UNO");
    }

    void OnMyTextChanged(PropertyChangedEventArgs e)
    {
        if (MyTextChanged != null) MyTextChanged(this, e);
    }

    void binding_Format(object sender, ConvertEventArgs e)
    {
        if (e.Value is Dictionary<string, string>)
        {
            Dictionary<string, string> source = (Dictionary<string, string>)e.Value;
            e.Value = source.Count.ToString();
        }
    }

    void binding_Parse(object sender, ConvertEventArgs e)
    {
        MessageBox.Show(e.DesiredType.ToString());
    }

    private void changemyClassButton_Click(object sender, EventArgs e)
    {
        myClass.AddStuff(myClass.Dic.Count.ToString(), "'" + myClass.Dic.Count.ToString() + "'");
    }

    private void changeMyTextButton_Click(object sender, EventArgs e)
    {
        MyText = "1234";
    }
}

public class MyClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Dictionary<string, string> Dic { get; set; }

    public MyClass()
    {
        Dic = new Dictionary<string, string>();
    }

    public void AddStuff(string key, string value)
    {
        Dic.Add(key, value);
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Dic"));
    }
}

Я пытаюсь связать MyText с myClass.Проблема в том, что функция binding_Parse никогда не вызывается.Я знаю, что, возможно, мог бы связать textBox1.Text напрямую с myClass, или что может быть тысяча других возможных способов сделать то, что я пытаюсь сделать, но это всего лишь практика;Я пытаюсь лучше понять привязку данных.Поэтому я хочу связать пользовательский объект с пользовательским свойством, чтобы я мог видеть процесс от начала до конца.Пользовательский объект - myClass, а пользовательское свойство - MyText.Я пробовал все виды вариаций, например реализацию INotifyPropertyChanged, но я не могу получить binding_Parse для вызова (я ожидаю, что он будет вызван, когда я вызову changeMyTextButton_Click).Я что-то упустил?

Редактировать: Проще говоря: я хочу написать пользовательский элемент управления со свойством string MyText, которое затем пользователь может связать с чем-то другим, таким же образомВы можете связать свойство TextBox Text с чем-то другим.Поэтому я не хочу связывать свойство элемента управления с объектом, я хочу написать элемент управления со свойством, которое затем пользователь может связать с объектом.

Ответы [ 2 ]

2 голосов
/ 22 октября 2010

ОК. Я понял это на тот случай, если у кого-то возникнет такая же проблема. Мне пришлось создать обработчик событий с именем MyTextChanged, чтобы Binding знал, что MyText меняется, и установить для свойства Binding s DataSourceUpdateMode значение OnPropertyChanged. Используя этот простой принцип, я могу связать пиксель на моем экране с остальной частью вселенной :). Вот код:

public partial class Form1 : Form
{
    public event EventHandler MyTextChanged;

    [Bindable(true)]
    public string MyText
    {
        get { return textBox1.Text; }
        set 
        {
            if (textBox1.Text != value)
            {
                textBox1.Text = value;
                OnMyTextChanged();
            }
        }
    }

    MyClass myClass { get; set; }

    public Form1()
    {
        InitializeComponent();
        myClass = new MyClass();
        Binding binding = new Binding("MyText", myClass, "Dic");
        binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
        binding.Parse += new ConvertEventHandler(binding_Parse);
        binding.Format += new ConvertEventHandler(binding_Format);
        DataBindings.Add(binding);
        myClass.AddStuff("uno", "UNO");
    }

    void OnMyTextChanged()
    {
        if (MyTextChanged != null) MyTextChanged(this, EventArgs.Empty);
    }

    void binding_Format(object sender, ConvertEventArgs e)
    {
        if (e.Value is Dictionary<string, string>)
        {
            Dictionary<string, string> source = (Dictionary<string, string>)e.Value;
            e.Value = source.Count.ToString();
        }
    }

    void binding_Parse(object sender, ConvertEventArgs e)
    {
        MessageBox.Show(e.DesiredType.ToString());

    }

    private void changemyClassButton_Click(object sender, EventArgs e)
    {
        myClass.AddStuff(myClass.Dic.Count.ToString(), "'" + myClass.Dic.Count.ToString() + "'");
    }

    private void changeMyTextButton_Click(object sender, EventArgs e)
    {
        MyText = "1234";
    }
}

public class MyClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Dictionary<string, string> Dic { get; set; }

    public MyClass()
    {
        Dic = new Dictionary<string, string>();
    }

    public void AddStuff(string key, string value)
    {
        Dic.Add(key, value);
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Dic"));
    }
}
1 голос
/ 22 октября 2010

Возможно, это поможет вам, понимая, когда выполняется событие Parse.

Чтобы увидеть, как работает binding_Parse, посмотрите этот образец:

public partial class Form1 : Form
{

    public MyClass myClass { get; set; }

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        myClass = new MyClass();
        myClass.AddStuff("uno", "UNO");

        Binding b = new Binding("Text", myClass, "Dic");
        b.Parse += new ConvertEventHandler(b_Parse);
        b.Format += new ConvertEventHandler(b_Format);
        textBox1.DataBindings.Add(b);
    }

    void b_Format(object sender, ConvertEventArgs e)
    {
        e.Value = (e.Value as Dictionary<string, string>)["uno"].ToString();
        textBox1.Text = e.Value.ToString();
    }

    void b_Parse(object sender, ConvertEventArgs e)
    {
        MessageBox.Show("This is executed when you lost focus\n\nI'm parsing your entered text: " + e.Value);
    }


}

У вас просто отладка. Нажмите на кнопку, и уведомление о событии Формат вызывается первым. Затем, если вы вручную измените значение textbox1.Text, при повторном нажатии на кнопку будет потерян фокус, а затем будет выполнено событие Parse.

Чтобы создать свой пользовательский элемент управления, также проверьте этот сайт .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...