WPF Databind перед сохранением - PullRequest
36 голосов
/ 12 сентября 2008

В моем приложении WPF у меня есть несколько текстовых ящиков с привязкой к данным. UpdateSourceTrigger для этих привязок LostFocus. Объект сохраняется с помощью меню Файл. У меня проблема в том, что можно ввести новое значение в TextBox, выбрать «Сохранить» в меню «Файл» и никогда не сохранять новое значение (видимое в TextBox), поскольку доступ к меню не приводит к удалению фокуса из TextBox , Как я могу это исправить? Есть ли способ заставить все элементы управления на странице привязать данные?

@ palehorse: Хорошая мысль. К сожалению, мне нужно использовать LostFocus в качестве моего UpdateSourceTrigger для поддержки требуемого типа проверки.

@ dmo: Я думал об этом. Однако, это похоже на действительно не элегантное решение относительно простой проблемы. Кроме того, требуется, чтобы на странице был какой-то элемент управления, который всегда виден для получения фокуса. Мое приложение, однако, имеет вкладки, поэтому такой элемент управления с готовностью не представляется.

@ Nidonocu: тот факт, что использование меню не сдвинуло фокус с TextBox, смутил меня. Это, однако, поведение, которое я вижу. Следующий простой пример демонстрирует мою проблему:

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ObjectDataProvider x:Key="MyItemProvider" />
    </Window.Resources>
    <DockPanel LastChildFill="True">
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="File">
                <MenuItem Header="Save" Click="MenuItem_Click" />
            </MenuItem>
        </Menu>
        <StackPanel DataContext="{Binding Source={StaticResource MyItemProvider}}">
            <Label Content="Enter some text and then File > Save:" />
            <TextBox Text="{Binding ValueA}" />
            <TextBox Text="{Binding ValueB}" />
        </StackPanel>
    </DockPanel>
</Window>
using System;
using System.Text;
using System.Windows;
using System.Windows.Data;

namespace WpfApplication2
{
    public partial class Window1 : Window
    {
        public MyItem Item
        {
            get { return (FindResource("MyItemProvider") as ObjectDataProvider).ObjectInstance as MyItem; }
            set { (FindResource("MyItemProvider") as ObjectDataProvider).ObjectInstance = value; }
        }

        public Window1()
        {
            InitializeComponent();
            Item = new MyItem();
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(string.Format("At the time of saving, the values in the TextBoxes are:\n'{0}'\nand\n'{1}'", Item.ValueA, Item.ValueB));
        }
    }

    public class MyItem
    {
        public string ValueA { get; set; }
        public string ValueB { get; set; }
    }
}

Ответы [ 13 ]

0 голосов
/ 01 июня 2011

Что вы думаете об этом? Я полагаю, что нашел способ сделать его немного более универсальным, используя рефлексию. Мне действительно не понравилась идея ведения списка, как некоторые другие примеры.

var currentControl = System.Windows.Input.Keyboard.FocusedElement;
if (currentControl != null)
{
    Type type = currentControl.GetType();
    if (type.GetMethod("MoveFocus") != null && type.GetMethod("Focus") != null)
    {
        try
        {
            type.GetMethod("MoveFocus").Invoke(currentControl, new object[] { new TraversalRequest(FocusNavigationDirection.Next) });
            type.GetMethod("Focus").Invoke(currentControl, null);
        }
        catch (Exception ex)
        {
            throw new Exception("Unable to handle unknown type: " + type.Name, ex);
        }
    }
}

Видите какие-нибудь проблемы с этим?

0 голосов
/ 23 октября 2008

Самый простой способ - установить фокус где-нибудь .
Вы можете немедленно вернуть фокус обратно, но установка фокуса в любом месте вызовет событие LostFocus на любой тип элемента управления и заставит его обновить свои вещи:

IInputElement x = System.Windows.Input.Keyboard.FocusedElement;
DummyField.Focus();
x.Focus();

Другим способом было бы получить сфокусированный элемент, получить элемент привязки из сфокусированного элемента и запустить обновление вручную. Пример для TextBox и ComboBox (вам нужно добавить любой тип элемента управления, который вам нужно поддерживать):

TextBox t = Keyboard.FocusedElement as TextBox;
if ((t != null) && (t.GetBindingExpression(TextBox.TextProperty) != null))
  t.GetBindingExpression(TextBox.TextProperty).UpdateSource();

ComboBox c = Keyboard.FocusedElement as ComboBox;
if ((c != null) && (c.GetBindingExpression(ComboBox.TextProperty) != null))
  c.GetBindingExpression(ComboBox.TextProperty).UpdateSource();
0 голосов
/ 12 сентября 2008

Изучая это, чтобы ответить на него, я немного сбит с толку тем, что происходит поведение, которое вы наблюдаете, конечно же, щелчок по меню «Файл» или что вы должны расфокусировать текстовое поле и установить его в меню?

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