Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > Binding in WinForms over WPF


Автор: Nordom 27.12.2010, 16:05
Господа, день добрый. Пишу проект на .NET 3.5, понадобился DateTimePicker, взял оный из Windows Forms.

Разбираюсь с проблемой байндинга к Windows Forms элементам. Нагуглил один интересный код, но, к сожалению, он не работает. Проблема в том, что мне он кажется абсолютно рабочим, видимо не хватает фактических знаний. Помогите, пожалуйста, разобраться, почему не работает как должно?

Код

    public class Proxy : FrameworkElement
    {
        public static readonly DependencyProperty InProperty;
        public static readonly DependencyProperty OutProperty;

        private delegate void Operation();

        public Proxy()
        {
            Visibility = Visibility.Collapsed;
        }

        static Proxy()
        {
            FrameworkPropertyMetadata inMetadata = new FrameworkPropertyMetadata(
                delegate(DependencyObject p, DependencyPropertyChangedEventArgs args)
                {
                    if (null != BindingOperations.GetBinding(p, OutProperty))
                        ((Proxy) p).Out = args.NewValue;
                }) {BindsTwoWayByDefault = false, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};

            InProperty = DependencyProperty.Register("In",
                typeof(object),
                typeof(Proxy),
                inMetadata);

            FrameworkPropertyMetadata outMetadata = new FrameworkPropertyMetadata(
                delegate(DependencyObject p, DependencyPropertyChangedEventArgs args)
                {
                    ValueSource source = DependencyPropertyHelper.GetValueSource(p, args.Property);

                    if (source.BaseValueSource != BaseValueSource.Local)
                    {
                        Proxy proxy = p as Proxy;
                        if (proxy != null)
                        {
                            object expected = proxy.In;
                            if (!ReferenceEquals(args.NewValue, expected))
                            {
                                Dispatcher.CurrentDispatcher.BeginInvoke(
                                    DispatcherPriority.DataBind, new Operation(delegate
                                                                                   {
                                                                                       proxy.Out = proxy.In;
                                                                                   }));
                            }
                        }
                    }
                }) {BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};

            OutProperty = DependencyProperty.Register("Out",
                typeof(object),
                typeof(Proxy),
                outMetadata);
        }

        public object In
        {
            get { return GetValue(InProperty); }
            set { SetValue(InProperty, value); }
        }

        public object Out
        {
            get { return GetValue(OutProperty); }
            set { SetValue(OutProperty, value); }
        }
    }



Пример вызова такой:

Код

<help:Proxy In="{Binding Path=CardOrder.MainInfo.CreationDate}" Out="{Binding ElementName=CreatedDate, Path=Value}" />
<WindowsFormsHost Name="windowsFormsHost1" MinWidth="120">
    <WinForms:DateTimePicker x:Name="CreatedDate"/>
</WindowsFormsHost>


Вообще, код интересный, в случае его допиливания — поможет решить много проблем и не мне одному.

Автор: Kaerus 27.12.2010, 16:46
Случай может быть и интересный. Но почему бы не использовать WPF'ый DatePicker?

В .NET 4 он встроенный, в .NET 3.5 надо отдельно ставить WFP Toolkit

Автор: Nordom 27.12.2010, 16:52
Потому что мне необходим DateTimePicker с возможностью выбора дня, но выводом и времени тоже. Плюс ко всему, WinForm-овский умеет Checkbox показывать, что тоже нужно.

Автор: Kaerus 27.12.2010, 17:01
Вот с временем http://datetimepickerwpf.codeplex.com/ и http://datetimepicker.codeplex.com/ . Всяко лучше чем с WinForms извращаться

Автор: Nordom 27.12.2010, 17:35
И его я смотрел, он прекрасен, но он использует компонент Calendar, специфичный для .NET 4, я же использую .NET 3.5, так как мой проект является встройкой в уже существующую систему и есть ограничение на версию .NET

К сожалению - так.

Еще какие-то предложения будут?((

Осенило. Взял DateTimePicker из верхней ссылки, прикрутил к нему Calendar из WPF Toolkit для 3.5 и получил рабочий прототип. Всем спасибо.

Автор: Kefir 27.12.2010, 17:56
Nordom, я на всякий случай скажу, что такие извращения я не очень люблю.

Что касается нерабочести - не уверен что понимаю для чего этот костыль был создан, но замечу что он (как и все другие байндинги) не будет работать при отсутствии INotifyPropertyChanged у источника (откуда дата берется) или же эта пропертия должня быть DependencyProperty. 

И ещё - если писать так как пишите вы (а имеено сначала назначая In, а потом Out), то начальное значение никогда не попадёт в нужные места, так как сначала забайндится In, возьмёт значение и не проставит это значение в Out (так как Out ещё не успел забайндится). Потом будет байндится Out, но поезд уже ушёл, и In бездействует до тех пор пока значение, куда он забайнден не обновится.

Если поменять их местами картина будет другая - сначала спокойненько байндится Out, потом байндится In и обновляет Out (ибо Out уже существует). А тру-ля-ля, всё в порядке.

В общем я вам честно скажу - если у вас нет желание досконально изучать и осознавать механизмы DependencyProperties и Binding - возьмите нормальный контрол и не мучайтесь smile Это я не в укор, это я предостерегаю. Ибо если вы начнёте этот костыль использовать, то рано или поздно вам придётся его дебажить.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)