powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Custom UserControl DependencyProperty
6 сообщений из 6, страница 1 из 1
Custom UserControl DependencyProperty
    #38922319
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день! Делаю такой вот контрол:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
 public partial class KSDatePicker : UserControl
    {
        #region Properties
        public static readonly DependencyProperty DateProperty = DependencyProperty.Register("SelectedDate", typeof(DateTime), typeof(KSDatePicker), new FrameworkPropertyMetadata(DateTime.Now, OnSelectedDateChanged));

        public DateTime SelectedDate
        {
            get { return (DateTime)GetValue(DateProperty); }
            set { SetValue(DateProperty, value); }
        }

        #endregion
        public KSDatePicker()
        {
            InitializeComponent();
            //Props

            //Events
            DateChangedEvent = EventManager.RegisterRoutedEvent("SelectedDateChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<DateTime>), typeof(KSDatePicker));
            (this.Content as FrameworkElement).DataContext = this;
        }

        #region CallBacks
        private static void OnSelectedDateChanged(DependencyObject _d, DependencyPropertyChangedEventArgs _e)
        {
            DateTime ndt = (DateTime)_e.NewValue;
            KSDatePicker picker = (KSDatePicker)_d;
            picker.SelectedDate = ndt;
        }

        private void ButtonMonthView_Click(object sender, RoutedEventArgs e)
        {
            if (popup1.IsOpen)
                popup1.IsOpen = false;
            else
                popup1.IsOpen = true;
        }
        #endregion

        public static RoutedEvent DateChangedEvent;
        public event RoutedPropertyChangedEventHandler<DateTime> SelectedDateChanged
        {
            add { AddHandler(DateChangedEvent, value); }
            remove { RemoveHandler(DateChangedEvent, value); }
        }

        private void ButtonNextDay_Click(object sender, RoutedEventArgs e)
        {
            OnSelectedDateChanged(this, new DependencyPropertyChangedEventArgs(DateProperty, SelectedDate, SelectedDate.AddDays(1)));
        }

        private void ButtonPreviousDay_Click(object sender, RoutedEventArgs e)
        { OnSelectedDateChanged(this, new DependencyPropertyChangedEventArgs(DateProperty, SelectedDate, SelectedDate.AddDays(-1))); }
    }



XAML контрола:


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
<UserControl x:Class="KsCustomControls.KSDatePicker"
             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="100" d:DesignWidth="350" 
             MaxHeight="100" MaxWidth="350"
             Name="Picker">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="3*"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" Name="ButtonPreviousDay" Content="{TemplateBinding Calendar.SelectedDate}" Click="ButtonPreviousDay_Click"></Button>
        <Border Grid.Column="1">
            <Viewbox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="vb">
                <TextBox Name="ButtonMonthView" PreviewMouseLeftButtonUp="ButtonMonthView_Click" Text="{Binding Path=SelectedDate, StringFormat=dd.MM.yy, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" IsReadOnly="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
            </Viewbox>
        </Border>
        <Button Grid.Column="2" Name="ButtonNextDay" Margin="0" Click="ButtonNextDay_Click" ></Button>

        <Popup Name="popup1"  VerticalOffset="20" StaysOpen="False" PopupAnimation="Scroll"  AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=ButtonMonthView}" IsOpen="False">
            <Grid>
                <Calendar Name="Calendar1" SelectedDate="{Binding Path=SelectedDate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"></Calendar>
            </Grid>
        </Popup>
    </Grid>
</UserControl>





использование контрола в тестовом окошке:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
<Window x:Class="Tester.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ksControls="clr-namespace:KsCustomControls;assembly=KsCustomControls"
        Title="MainWindow" Height="350" Width="525" Name="mw">
    <Grid>
        <TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <TabItem Header="DatePicker">
                <Grid>
                    <!--<ksControls:TEST></ksControls:TEST>-->
                    <ksControls:KSDatePicker SelectedDate="{Binding date, Mode=TwoWay}" SelectedDateChanged="KSDatePicker_SelectedDateChanged"></ksControls:KSDatePicker>
                    <Label Content="{Binding date}"  HorizontalAlignment="Left" Margin="49,24,0,0" VerticalAlignment="Top" Height="30" Width="136"/>
                </Grid>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
        </TabControl>

    </Grid>
</Window>



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
    public partial class MainWindow : Window
    {
        public DateTime date { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            date = DateTime.Now;
        }

        private void KSDatePicker_SelectedDateChanged(object sender, RoutedPropertyChangedEventArgs<DateTime> e)
        {
            MessageBox.Show(date.ToString());
        }
    }




Подскажите, пожалуйста, что я сделал не так, что надо сделать, чтобы у меня выстреливало событие KSDatePicker_SelectedDateChanged в окне?
Дата меняется, а события я не получаю. Соответственно не меняется и значение в Label`е.
...
Рейтинг: 0 / 0
Custom UserControl DependencyProperty
    #38923115
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,

не увидел в твоем коде, где ты возбуждаешь это события.
по идее в этом куске кода должно возбуждаться маршрутизирующие событие, но оно там не происходит.
Код: c#
1.
2.
3.
4.
5.
6.
       private static void OnSelectedDateChanged(DependencyObject _d, DependencyPropertyChangedEventArgs _e)
        {
            DateTime ndt = (DateTime)_e.NewValue;
            KSDatePicker picker = (KSDatePicker)_d;
            picker.SelectedDate = ndt;
        }



нужно в этом методе добавить
Код: c#
1.
base.RaiseEvent(_e);
...
Рейтинг: 0 / 0
Custom UserControl DependencyProperty
    #38923138
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
нужно в этом методе добавить
Код: c#
1.
base.RaiseEvent(_e);


сори, параметрам нужно передавать RoutedEventArgs в котором задается идентификатор, источник и прочее.

Код: c#
1.
2.
RoutedEventArgs е = new RoutedEventArgs(ButtonBase.ClickEvent, this);
base.RaiseEvent(e);
...
Рейтинг: 0 / 0
Custom UserControl DependencyProperty
    #38923358
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Говорит что base нельзя использовать в статичном контексте!
...
Рейтинг: 0 / 0
Custom UserControl DependencyProperty
    #38923558
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Значит добился я с горем пополам, чтобы вызов события происходил. Вот код контрола (xaml остался тем же):


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
#region
using System;
using System.Windows;
using System.Windows.Controls;



#endregion


namespace KsCustomControls
{

    public partial class KSDatePicker : UserControl
    {
        public KSDatePicker()
        {
            InitializeComponent();
            (Content as FrameworkElement).DataContext = this;
        }

        #region Properties

        #region SelectedDate
        public static readonly DependencyProperty DateProperty = DependencyProperty.Register("SelectedDate", typeof (DateTime), typeof (KSDatePicker), new FrameworkPropertyMetadata(DateTime.Now, OnSelectedDateChangedCallback));

        // RE: changed event identifier & registration
        public static readonly RoutedEvent SelectedDateChangedEvent =
            EventManager.RegisterRoutedEvent(
                "SelectedDateChanged",
                RoutingStrategy.Bubble,
                typeof (RoutedPropertyChangedEventHandler<DateTime>),
                typeof (KSDatePicker));

        public DateTime SelectedDate { get { return (DateTime) GetValue(DateProperty); } set { SetValue(DateProperty, value); } }

        // RE: changed event
        public event RoutedPropertyChangedEventHandler<DateTime> SelectedDateChanged { add { AddHandler(SelectedDateChangedEvent, value); } remove { RemoveHandler(SelectedDateChangedEvent, value); } }

        // RE: use a protected virtual to raise event
        protected virtual void OnSelectedDateChanged(DateTime oldValue, DateTime newValue)
        {
            var e =
                new RoutedPropertyChangedEventArgs<DateTime>(oldValue, newValue);
            e.RoutedEvent = SelectedDateChangedEvent;
            RaiseEvent(e);
        }

        private static void OnSelectedDateChangedCallback(DependencyObject _d, DependencyPropertyChangedEventArgs _e)
        {
            var ndt = (DateTime) _e.NewValue;
            var picker = (KSDatePicker) _d;
            picker.SelectedDate = ndt;
            picker.OnSelectedDateChanged((DateTime) _e.OldValue, (DateTime) _e.NewValue);
        }
        #endregion

        #endregion

        private void ButtonNextDay_Click(object sender, RoutedEventArgs e) { OnSelectedDateChangedCallback(this, new DependencyPropertyChangedEventArgs(DateProperty, SelectedDate, SelectedDate.AddDays(1))); }

        private void ButtonPreviousDay_Click(object sender, RoutedEventArgs e) { OnSelectedDateChangedCallback(this, new DependencyPropertyChangedEventArgs(DateProperty, SelectedDate, SelectedDate.AddDays(-1))); }

        private void ButtonMonthView_Click(object sender, RoutedEventArgs e)
        {
            if (popup1.IsOpen)
                popup1.IsOpen = false;
            else
                popup1.IsOpen = true;
        }
    }

}




Вот его использование на форме:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
<Window x:Class="Tester.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ksControls="clr-namespace:KsCustomControls;assembly=KsCustomControls"
        xmlns:tester="clr-namespace:Tester"
        Title="MainWindow" Height="350" Width="525" Name="mw">
    <Grid>
        <TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <TabItem Header="DatePicker">
                <Grid Margin="0,0,0,150">
                    <ksControls:KSDatePicker SelectedDate="{Binding date, Mode=TwoWay}" SelectedDateChanged="KSDatePicker_OnSelectedDateChanged"></ksControls:KSDatePicker>
                    <Label Content="{Binding date, Mode=OneWay}"  HorizontalAlignment="Left" Margin="49,24,0,0" VerticalAlignment="Top" Height="30" Width="136"/>
                </Grid>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
        </TabControl>

    </Grid>
</Window>




И вот такой код в окне:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    public partial class MainWindow : Window
    {
        public DateTime date { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            date = DateTime.Now;
        }
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        private void KSDatePicker_OnSelectedDateChanged(object _sender, RoutedPropertyChangedEventArgs<DateTime> _e)
        {
            //MessageBox.Show("HURAAAAA!");
            RaisePropertyChanged("date");
        }
    }





Помогите, пожалуйста, найти ответы на след. вопросы:
Если вы попробуете запустить этот код, то увидите, что событие KSDatePicker_OnSelectedDateChanged выстреливает два раза.
1) Как этого избежать?

2) Почему даже с учётом того, что я реализовал RaisePropertyChanged у меня не происходит обновление Label`a на форме? Ведь он забинден на свойство date!

3) Как мне сделать контрол в отдельном классе и унаследовать его от, к примеру, Button? Если я объявляю такой контрол ниже класса Window в тестовой программе, то всё хорошо. Если объявляю такой класс в сборке, чтобы потом из неё его тягать, то получаю "base class блабла_название_класса differs from declared"

4) Есть у кого внятный урок по созданию своих контролов ОТ и ДО?
...
Рейтинг: 0 / 0
Custom UserControl DependencyProperty
    #38923647
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,

Ответ на вопрос 2:
Надо было унаследовать интерфейс INotifyPropertyChanged:

public partial class MainWindow : Window , INotifyPropertyChanged
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Custom UserControl DependencyProperty
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]