На какой странице я должен объявить опцию Binding с пользовательским контролем в WPF - PullRequest
0 голосов
/ 25 декабря 2018

Я новичок в создании пользовательских элементов управления в wpf.
Я совершенно не понимаю технику привязки с пользовательским элементом управления.
Позвольте мне показать вам мое упражнение.

Я объявляю свой пользовательский элемент управления в файле cs

public class CustomControl1 : Control
{
    static CustomControl1()
    {
        DefaultStyleKeyProperty.OverrideMetadata
            (typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1))
            );
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextaaProperty =
        DependencyProperty.Register(
            "Textaa", 
            typeof(string), typeof(CustomControl1),
            new PropertyMetadata(null));

    public string Textaa
    {
        get { return (string)GetValue(TextaaProperty); }
        set { SetValue(TextaaProperty, value); }
    }
 }

и в Generic.xaml, я объявил Template Style для своего настраиваемого элемента управления в Generic.xaml.

<Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Background" Value="DimGray"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <TextBox Background="{TemplateBinding Background}" 
                           Text="{Binding Textaa, 
                                 RelativeSource={RelativeSource TemplatedParent}}">
                </TextBox>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Чтобы создать текст для моего элемента управления, я создал класс My Custom для объекта Data, который просто имеет свойство name и просто наследуется от INPC

    public MainWindow()
    {
        InitializeComponent();
        DataContext = new DataObject() { name = "Jeong Yo Han" };
    }

    public class DataObject : INotifyPropertyChanged
    {
        private string _name;
        public string name
        {
            get { return _name; }
            set {
                _name = value;
                onPropertyChanged("name");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void onPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }  

На своей странице MainWindow я объявил тег пользовательского элемента управления

<Grid>
    <cc:CustomControl1 Background="Red" 
                       Textaa="{Binding name ,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
    </cc:CustomControl1>
</Grid>

Я попытался проверить, работает ли templatedParent в Template Style для двусторонней привязки.(см. RelativeSource = {Rela ... TemplatedParent}).

и я запускаю свою программу, чтобы увидеть, когда я получу свойство установщика имени попадания в классе DataObject.даже я добавляю UpdateSourceTrigger = PropertyChanged, но он не работает, когда я меняю текст в TextBox.Это работает, когда я потерял фокус на этом, даже я набрал UpdateSourceTrigger = PropertyChanged.

Таким образом, я изменил свой источник Как следующий источник.

<!-- in Generic.xaml (Template style) -->
<TextBox Background="{TemplateBinding Background}" 
                           Text="{Binding Textaa, 
                           UpdateSourceTrigger=PropertyChanged,
                                 RelativeSource={RelativeSource TemplatedParent}}">
</TextBox>
<!--- in MainWindow.xaml--->
<cc:CustomControl1 Background="Red" 
                       Textaa="{Binding name ,Mode=TwoWay}" >
 </cc:CustomControl1>

это работает хорошо, как я ожидал.
и последующее не работает, Не ожидал.

<!-- in Generic.xaml (Template style) -->
<TextBox Background="{TemplateBinding Background}" 
                           Text="{Binding Textaa, 
                           UpdateSourceTrigger=PropertyChanged, Mode=TwoWay,
                                 RelativeSource={RelativeSource TemplatedParent}}">
</TextBox>
<!--- in MainWindow.xaml--->
<cc:CustomControl1 Background="Red" 
                       Textaa="{Binding name}" >
 </cc:CustomControl1>

Но я не совсем понимаю, почему я должен поместить опцию UpdateSourceTrigger в StyleTemplate и опцию Mode = TwoWayBinding для непосредственного свойства зависимости Textaa тега customcontrol.

Мне нужно пояснение.Спасибо за прочтение.

за помощь в понимании. Ниже я добавил реоп для моего источника.

Нажмите здесь, чтобы просмотреть весь источник

1 Ответ

0 голосов
/ 25 декабря 2018

Поведение по умолчанию для обновления свойства источника свойства Binding of Text объекта TextBox: LostFocus.

См. Замечания на странице TextBox.Text :

При использовании в сценариях привязки данных это свойство использует поведение обновления по умолчанию UpdateSourceTrigger.LostFocus.

Однако вам не нужно устанавливать Mode=TwoWay, потому что это уже значение по умолчанию.Поэтому объявление TextBox должно выглядеть следующим образом:

<TextBox Background="{TemplateBinding Background}" 
         Text="{Binding Textaa,
                UpdateSourceTrigger=PropertyChanged,
                RelativeSource={RelativeSource TemplatedParent}}" />

Нет необходимости устанавливать UpdateSourceTrigger=PropertyChanged для Binding вашего свойства Textaa, поскольку (в отличие от TextBlock.Text),поведение по умолчанию для вашего пользовательского свойства зависимости уже PropertyChanged.

Вы также можете зарегистрировать свое свойство таким образом, чтобы оно по умолчанию связывало его с двух сторон, чтобы вам не пришлось устанавливать Mode=TwoWayна Textaa Binding:

public static readonly DependencyProperty TextaaProperty =
    DependencyProperty.Register(
        nameof(Textaa), typeof(string), typeof(CustomControl1),
        new FrameworkPropertyMetadata(
            null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Теперь вы можете связать свойство Textaa следующим образом:

<cc:CustomControl1 Textaa="{Binding name}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...