Привязка с использованием стиля никогда не выпускается - PullRequest
0 голосов
/ 10 января 2019

и с новым годом.

Вот мой вопрос, выходит ли когда-либо привязка, созданная в стиле, из области видимости.

Позвольте мне объяснить, у меня есть текстовый блок с множественным связыванием значений двух элементов в списке «Имена», список строк в модели представления.

Я получаю доступ к этим элементам по индексу с помощью магической строки в xaml (yikes, я знаю, я не знаю, как поступить иначе, если я установил привязку к коллекции, событие itemChanged не вызывает привязку ...) .

Мне нужно получить изменения в значении, и я действительно не хочу создавать какие-либо средства доступа. Я хотел бы, чтобы все было обработано в представлении.

<TextBlock>
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Text"
                        Value="" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsGroupedBy, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource  Mode=FindAncestor, AncestorType=Window}}"
                                 Value="True">
                        <Setter Property="Text">
                            <Setter.Value>
                                <MultiBinding Converter="{StaticResource ConcatStringConvertor}"
                                              UpdateSourceTrigger="PropertyChanged"
                                              Mode="OneWay">
                                    <Binding Path="Names[1]"
                                             RelativeSource="{RelativeSource  Mode=FindAncestor, AncestorType=Window}"
                                             UpdateSourceTrigger="PropertyChanged" />
                                    <Binding Path="Names[2]"
                                             RelativeSource="{RelativeSource  Mode=FindAncestor, AncestorType=Window}"
                                             UpdateSourceTrigger="PropertyChanged" />
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsGroupedBy, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource  Mode=FindAncestor, AncestorType=Window}}"
                                 Value="False">
                        <Setter Property="Text" Value="0">
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>

Я установил эту привязку в стиле с помощью источника данных на IsGroupedBy == true. текст текстового поля устанавливается в 0, если «IsGroupedBy == false». Это работает (когда useBinding имеет значение true, два моих значения объединены в текстовом блоке, в противном случае его значение равно «0».

Моя проблема возникает сейчас, когда я впервые устанавливаю для useBinding значение true, привязка создается. С этого момента, если я изменяю (обычно я очищаю его) мой список EVEN WITH IsGroupedBy TO FALSE, привязка оценивается;

Затем я получаю исключение аргумента для индекса вне диапазона. (который молчит и конечный пользователь никогда не узнает, но он не очень чистый и ориентированный на производительность ...)

System.Windows.Data Warning: 17 : Cannot get 'Item[]' value (type 'String') from 'Names' (type 'ObservableCollection`1'). BindingExpression:Path=Names[1]; DataItem='MainWindow' (Name=''); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: ...

Я думал, что условное связывание решит эту проблему, но не ...

Я открыт для любых решений (особенно, если я могу найти способ удалить эти Имена [1] из привязок)

PS: простите за мой английский.

EDIT :
    public ObservableCollection<string> Names { get; set; }

РЕДАКТИРОВАТЬ 2: Я попробовал другой подход, я использую привязку приоритета, например так:

<TextBlock.Text>
                <PriorityBinding>
                    <Binding Path="IsGroupedBy"
                             Converter="{StaticResource NotFalseToUnsetValueConverter}"
                             UpdateSourceTrigger="PropertyChanged"
                             RelativeSource="{RelativeSource  Mode=FindAncestor, AncestorType=Window}" />
                    <Binding Path="Names[1]"
                             UpdateSourceTrigger="PropertyChanged"
                             RelativeSource="{RelativeSource  Mode=FindAncestor, AncestorType=Window}" />
                </PriorityBinding>
            </TextBlock.Text>


public class NotFalseToUnsetValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var groupBy = value as bool?;
            return (groupBy.Value == true)
                ? DependencyProperty.UnsetValue // evaluate next binding which is on array
                : "dont bind array"; // stop at first binding and dont check array  
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
    }

Но у меня возникла та же проблема, когда я впервые оцениваю привязку для Имен [1], она как-то регистрируется где-то.

И даже если я перестану привязываться ко второй привязке, любое опустошение в списке отправит ошибку:

System.Windows.Data Warning: 17 : Cannot get 'Item[]' value (type 'String') from 'Names' (type 'ObservableCollection`1'). BindingExpression:Path=Names[1]; DataItem='MainWindow' (Name=''); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException

РЕДАКТИРОВАТЬ 3: Вот настоящая привязка:

<DataTemplate x:Key="customGroupValueTemplate">
            <Grid Width="{Binding ElementName=uxGrid, Path=ActualWidth}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="60" />
                </Grid.ColumnDefinitions>
                <dxe:CheckEdit  Grid.Column="0"
                                Initialized="cbGroupSummary_Initialized"
                                Checked="cbGroupSummary_Checked"
                                Unchecked="cbGroupSummary_Unchecked"
                                Content="{Binding Value}" />
                <TextBlock Grid.Column="2"
                           Margin="10,0,0,0"
                           VerticalAlignment="Center"
                           Text="{Binding Path=(dxg:RowData.RowData).GroupSummaryData[0].Text, RelativeSource={RelativeSource TemplatedParent}}" />
                <TextBlock  Grid.Column="4"
                            Margin="10,0,0,0"
                            HorizontalAlignment="Right"
                            VerticalAlignment="Center">
                    <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource GetPercentAsTextConv}"
                                      UpdateSourceTrigger="PropertyChanged"
                                      Mode="OneWay">
                            <Binding Path="(dxg:RowData.RowData).GroupSummaryData[1].Value"
                                     RelativeSource="{RelativeSource Self}"
                                     UpdateSourceTrigger="PropertyChanged" />
                            <Binding Path="(dxg:RowData.RowData).GroupSummaryData[2].Value"
                                     RelativeSource="{RelativeSource Self}"
                                     UpdateSourceTrigger="PropertyChanged" />
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
                <ProgressBar  Grid.Column="5"
                              Width="100"
                              Height="10"
                              Margin="10 0 0 0"
                              HorizontalAlignment="Right"
                              VerticalAlignment="Center">
                    <ProgressBar.Value>
                        <MultiBinding Converter="{StaticResource GetPercentConv}"
                                      UpdateSourceTrigger="PropertyChanged"
                                      Mode="OneWay">
                            <Binding Path="(dxg:RowData.RowData).GroupSummaryData[1].Value"
                                     RelativeSource="{RelativeSource TemplatedParent}"
                                     UpdateSourceTrigger="PropertyChanged" />
                            <Binding Path="(dxg:RowData.RowData).GroupSummaryData[2].Value"
                                     RelativeSource="{RelativeSource TemplatedParent}"
                                     UpdateSourceTrigger="PropertyChanged" />
                        </MultiBinding>
                    </ProgressBar.Value>
                </ProgressBar>
            </Grid>
        </DataTemplate>

Обратите внимание, что это шаблон.

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Почему вы используете мультисвязывание?

<TextBlock>
    <TextBlock.Style>
        <Style TargetType="TextBlock">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=IsGroupedBy, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource  Mode=FindAncestor, AncestorType=Window}}"}" Value="True">
                    <Setter Property="Text" Value="{Binding Path=Names, Converter={StaticResource FirstTwoListValuesElemToStringConverter}}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=IsGroupedBy, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource  Mode=FindAncestor, AncestorType=Window}}"}" Value="False">
                    <Setter Property="Text" Value="0"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

и для конвертера

[ValueConversion(typeof(ObservableCollection<string>), typeof(string))]
class FirstTwoListValuesElemToStringConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        System.Collections.ObjectModel.ObservableCollection<string> names = ((System.Collections.ObjectModel.ObservableCollection<string>)value);
        if ((names != null) && (names.Count > 2))
            return names.FirstOrDefault() + names.ElementAtOrDefault(1);
        else
            return System.Windows.DependencyProperty.UnsetValue;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
}
0 голосов
/ 10 января 2019

Я думаю, что вы имеете в виду IsGroupedBy вместо useBinding. не очень хорошее решение, но вы можете заменить Binding Path="Names[1]" на Binding Path="Names.ElementAtOrDefault(1)"

...