Как передать значение UpdateSourceTrigger в UserControl или обновить его во время выполнения? - PullRequest
5 голосов
/ 19 марта 2019

Я столкнулся с проблемой со свойством UpdateSourceTrigger. У меня есть UserControl с именем LabelWithTextBox, где UpdateSourceTrigger (On Text Property) не определен (поэтому имеет значение по умолчанию). Так должно быть из-за производительности (текст должен обновляться, когда фокус выходит за пределы текстового поля).

Но теперь у меня есть случай, когда должен использоваться UserControl, и обновление должно происходить как пользовательские типы, поэтому я хочу установить UpdateSourceTrigger в PropertyChanged.

В идеале лучшим решением было бы наследование свойства UpdateSourceTrigger. Пользователь использует в своем Просмотр UserControl и определяет UpdateSourceTrigger = PropertyChanged, эта информация передается в мой UserControl, и все работает, как ожидалось. Кто-нибудь знает, как мне это заархивировать?

Какие еще есть варианты? Как я могу изменить свойство UpdateSourceTrigger во время выполнения?

Вот соответствующий код UserControl (код позади):

public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
    "Text",
    typeof(string),
    typeof(LabelWithTextBox),
    new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public string Text
{
    get { return (string)this.GetValue(TextProperty); }
    set { this.SetValue(TextProperty, value); }
}

А вот код UserControl (Xaml):

<Grid Grid.Column="1">
            <telerik:RadWatermarkTextBox TextChanged="TextBoxBase_OnTextChanged"
                                         Name="TextBox"
                                         Text="{Binding Text, Mode=TwoWay, ElementName=userControl}"
                                         WatermarkContent="{Binding Placeholder, Mode=TwoWay, ElementName=userControl}"
                                         TextWrapping="{Binding TextWrap, Mode=TwoWay, ElementName=userControl}"
                                         AcceptsReturn="{Binding AcceptsReturn, Mode=TwoWay, ElementName=userControl}"
                                         VerticalScrollBarVisibility="{Binding VerticalScrollBarVisibility, Mode=TwoWay, ElementName=userControl}"
                                         MinLines="{Binding MinLines, Mode=TwoWay, ElementName=userControl}"
                                         MaxLines="{Binding MaxLines, Mode=TwoWay, ElementName=userControl}"
                                         IsReadOnly="{Binding IsReadOnly, ElementName=userControl}"/>
    ....

Если добавить UpdateSourceTrigger = PropertyChanged в Text, все будет работать как положено. Но я этого не хочу.

Вот, например, как кто-то может использовать UserControl в своем представлении. То, что я ищу, - это способ передать значение UpdateSourceTrigger моему UserControl, но как?

<controls:LabelWithTextBox
                    Grid.Row="1"
                    Margin="0,5,0,0"
                    Label="Excel Blattname:"
                    SharedSizeGroup="LabelsX"
                    Text="{Binding SheetName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

Ответы [ 2 ]

2 голосов
/ 19 марта 2019

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

Ваш элемент управления может предоставить свойство TextBinding:

public partial class LabelWithTextBox : UserControl
{
    public LabelWithTextBox()
    {
        InitializeComponent();
    }

    private BindingBase textBinding;

    public BindingBase TextBinding
    {
        get { return textBinding; }
        set
        {
            textBinding = value;
            TextBox.SetBinding(RadWatermarkTextBox.TextProperty, textBinding);
        }
    }
}

, которому вы бы присвоили привязку типа

<controls:LabelWithTextBox
  TextBinding="{Binding SheetName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

, который затем напрямую передается RadWatermarkTextBox.

Недостатком является, конечно, то, что вы можете назначить только Binding и ничего больше.


Однако вы также можете использовать свойство зависимостей Text и проверять его значение при загрузке элемента управления. Если значением является Binding, вы можете использовать его следующим образом:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    var binding = GetBindingExpression(TextProperty)?.ParentBinding;

    if (binding != null)
    {
        TextBox.SetBinding(RadWatermarkTextBox.TextProperty, binding);
    }
}
2 голосов
/ 19 марта 2019

Мне не совсем ясно, чего вы хотите достичь

Вы можете установить Binding на RadWatermarkTextBox в коде, а не в XAML.

РЕДАКТИРОВАТЬ:

Теперь я вижу, что вы хотите :)

Добавьте его в свой пользовательский элемент управления:

public bool UpdateOnPropChanged
{
    get
    {
        return _updateOnPropChanged;
    }
    set
    {
        _updateOnPropChanged = value;
        this.TextBox.SetBinding(TextBox.TextProperty, new Binding("Text") { RelativeSource=new RelativeSource(RelativeSourceMode.FindAncestor) { AncestorType=typeof(LabelWithTextBox) }, UpdateSourceTrigger = _updateOnPropChanged ? UpdateSourceTrigger.PropertyChanged : UpdateSourceTrigger.LostFocus });
    }
}
private bool _updateOnPropChanged;

И вы можете использовать его так:

<controls:LabelWithTextBox UpdateOnPropChanged="false"/>
...