c# - 使用 StackPanel 包围控件时出现元素名称绑定(bind)错误

标签 c# wpf xaml binding

我在使用 Element Name 绑定(bind) XAML 时遇到了一个奇怪的问题。

一切正常,但是当我用 StackPanel 包围控件和用户控件时,我遇到了绑定(bind)错误。

我将两个用户控件的可见性与两个切换按钮(IsDeadToggle 和 IsNotTransportable)的 IsChecked 属性绑定(bind)在一起,并使用 ElementName。

<ItemsControl AlternationCount="100" FocusVisualStyle="{x:Null}" HorizontalAlignment="Left">
                        <ItemsControl.ItemsSource>
                            <CompositeCollection>
                                <StackPanel x:Name="FirstSP" Margin="0,0,10,0">
                                    <TextBlock FocusVisualStyle="{x:Null}"
                                               Style="{StaticResource WrapTitleAddTextBlock}"
                                               Text="{x:Static languages:ResCommon.General}" />
                                    <StackPanel x:Name="BuggedSP" Background="{StaticResource WrapBackground}">
                                        <StackPanel Orientation="Horizontal"
                                                    Margin="10,20">
                                            <RadioButton Content="{x:Static languages:ResCommon.Man}"
                                                         IsChecked="{Binding Path=Add.Presenter.Customer.Gender, Mode=TwoWay, Converter={StaticResource EnumMatchToBooleanConverter}, ConverterParameter=Male}" />
                                            <RadioButton x:Name="IsWoman"
                                                         Content="{x:Static languages:ResCommon.Woman}"
                                                         IsChecked="{Binding Path=Add.Presenter.Customer.Gender,
                                                                             Mode=TwoWay,
                                                                             Converter={StaticResource EnumMatchToBooleanConverter},
                                                                             ConverterParameter=Female}" />
                                        </StackPanel>
                                        <formElement:LabelComboBox Margin="{StaticResource ControlAddMargin}"
                                                                   Visibility="{Binding Add.Presenter.Customer.CustomerIdInsured, Converter={StaticResource NullToVisibilityConverter}}"
                                                                   LabelName="{x:Static languages:ResCommon.BeneficiaryType}"
                                                                   ComboBoxDisplayMemberItem="Translation"
                                                                   ComboBoxSelectedValueItem="Enum"
                                                                   ComboBoxItems="{Binding Source={me:EnumValues EnumType=entities:TypeOfBeneficiary, ResourceName='Languages.ResEnum,Languages'}}"
                                                                   ComboBoxSelectedItem="{Binding Add.Presenter.Customer.TypeOfBeneficiary}" />
                                        <formElement:InnerLabelBox Margin="{StaticResource ControlAddMargin}"
                                                                   LabelName="{x:Static languages:ResCommon.LastName}"
                                                                   TextBoxValue="{Binding Add.Presenter.Customer.LastName,
                                                                                 Converter={StaticResource StringToUpperStringConverter},
                                                                                 Mode=TwoWay,
                                                                                 ValidatesOnDataErrors=true,
                                                                                 NotifyOnValidationError=true}" />
                                        <formElement:LabelBox Margin="{StaticResource ControlAddMargin}"
                                                              LabelName="{x:Static languages:ResCommon.MaidenName}"
                                                              TextBoxValue="{Binding Add.Presenter.Customer.MaidenName,
                                                                                 Converter={StaticResource StringToUpperStringConverter},
                                                                                 Mode=TwoWay,
                                                                                 ValidatesOnDataErrors=true,
                                                                                 NotifyOnValidationError=true}"
                                                              Visibility="{Binding IsChecked,
                                                                               ElementName=IsWoman,
                                                                               Converter={StaticResource BooleanToVisibilityConverter}}" />
                                        <formElement:InnerLabelBox Margin="{StaticResource ControlAddMargin}"
                                                                   LabelName="{x:Static languages:ResCommon.FirstName}"
                                                                   TextBoxValue="{Binding Add.Presenter.Customer.FirstName,
                                                                                 Converter={StaticResource StringToCapitalizeStringConverter},
                                                                                 Mode=TwoWay,
                                                                                 ValidatesOnDataErrors=true,
                                                                                 NotifyOnValidationError=true}" />
                                        <resources:DateTimePickerTextBoxSwitch
                                            Margin="{StaticResource ControlAddMargin}"
                                            TextBoxValue="{Binding Add.Presenter.Customer.BirthDateCustom,
                                                                                Mode=TwoWay,
                                                                                ValidatesOnDataErrors=true,
                                                                                NotifyOnValidationError=true}"
                                            DateTimeValue="{Binding Add.Presenter.Customer.BirthDate, Mode=TwoWay}" />
                                        <Grid Width="220" Margin="10,10,10,0">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"></ColumnDefinition>
                                                <ColumnDefinition Width="60"></ColumnDefinition>
                                            </Grid.ColumnDefinitions>
                                            <TextBlock Style="{StaticResource DarkSmallFontStyle}" Text="{x:Static languages:ResCustomers.IsDead}"></TextBlock>
                                            <ToggleButton Grid.Column="1" IsChecked="{Binding Add.Presenter.Customer.IsAlive, Mode=TwoWay}"
                                                          Style="{StaticResource OnOffToggleButton}"
                                                          x:Name="IsDeadToggle" />
                                        </Grid>
                                        <formElement:LabelDatePicker Margin="{StaticResource ControlAddMargin}"
                                                                     DatePickerValue="{Binding Add.Presenter.Customer.DeathDate,
                                                                                           Mode=TwoWay}"
                                                                     LabelName="{x:Static languages:ResCustomers.DeathDate}"
                                                                     Visibility="{Binding IsChecked,
                                                                                      ElementName=IsDeadToggle,
                                                                                      Converter={StaticResource BooleanToVisibilityConverterCustomInvert}}"
                                                                     PrintEnum="WithDate" />
                                        <Grid Width="220" Margin="10,10,10,0">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"></ColumnDefinition>
                                                <ColumnDefinition Width="60"></ColumnDefinition>
                                            </Grid.ColumnDefinitions>
                                            <TextBlock Style="{StaticResource DarkSmallFontStyle}" Text="{x:Static languages:ResCustomers.IsNoTransportable}"></TextBlock>
                                            <ToggleButton Grid.Column="1" IsChecked="{Binding Add.Presenter.Customer.IsNoTransportable, Mode=TwoWay}"
                                                          Style="{StaticResource OnOffToggleButton}"
                                                          x:Name="IsNotTransportableToggle" />
                                        </Grid>
                                        <formElement:MultiLineTextBox
                                            Margin="{StaticResource ControlAddMargin}"
                                            LabelName="{x:Static languages:ResCustomers.NoTransportComment}"
                                            TextBoxValue="{Binding Add.Presenter.Customer.NoTransportComment,
                                                                                         Mode=TwoWay,
                                                                                         ValidatesOnDataErrors=true,
                                                                                         NotifyOnValidationError=true}"
                                            Visibility="{Binding IsChecked,
                                                                                       ElementName=IsNotTransportableToggle,
                                                                                       Converter={StaticResource BooleanToVisibilityConverterCustom}}" />

                                    </StackPanel>
                                </StackPanel>

添加的StackPanel是具有以下属性的

x:name="BuggedSP"

错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=IsDeadToggle'. BindingExpression:Path=IsChecked; DataItem=null; target element is 'LabelDatePicker' (Name='UCLabelDatePicker'); target property is 'Visibility' (type 'Visibility')

编辑 1:

如果我删除 FirstSP StackPanel,它又可以工作了……我开始认为这是一个深度问题。但我不明白为什么我的绑定(bind)在特定深度级别不起作用

编辑 2:

如果我删除切换按钮周围的网格,它也不起作用,因此切换是否与用户控件处于同一级别并不重要。

因此有了 VisualTree(WPF Tree WPF Tree Visualizer)一切都很好:

<WrapPanel>
    <ItemsControl>
        <ItemsPresenter>
            <WrapPanel>
                <StackPanel>
                    <!-- List of UC and Toggles-->

这个不行:

<WrapPanel>
    <ItemsControl>
        <ItemsPresenter>
            <WrapPanel>
                <StackPanel>
                    <StackPanel x:Name="BuggedSp">        
                    <!-- List of UC and Toggles-->

最佳答案

我可以看到您的 ToggleButtonIsDeadToggle,在 IsChecked 属性上有两种方式绑定(bind)到 Add.Presenter .Customer.IsAlive 数据上下文中的属性。

我还看到您正在尝试将 LabelDatePickerVisibility 属性绑定(bind)到 ToggleButton 的 IsChecked 属性,使用转换器进行反转,然后将 bool 值转换为 System.Windows.Visibility

由于 ToggleButtonLabelDatePicker 共享相同的数据上下文,我将简单地将 LabelDatePicker 的可见性绑定(bind)到相同的属性数据上下文:

<formElement:LabelDatePicker
    Margin="{StaticResource ControlAddMargin}"
    DatePickerValue="{Binding Add.Presenter.Customer.DeathDate, Mode=TwoWay}"
    LabelName="{x:Static languages:ResCustomers.DeathDate}"
    Visibility="{Binding Add.Presenter.Customer.IsAlive, Converter={StaticResource BooleanToVisibilityConverterCustomInvert}}"
    PrintEnum="WithDate" />

注意:数据上下文(Customer 对象)需要实现 System.ComponentModel.INotifyPropertyChanged 并且 IsAlive 属性需要提高带有属性名称的 PropertyChanged 事件,以确保 LabelDatePickerIsDeadToggle 复选框更改其值时得到正确通知以重新绑定(bind)。

有关详细信息,请参阅 MSDN:http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx

通常,我倾向于避免元素到元素的绑定(bind),以支持数据上下文中的公共(public)属性。这种方式更易于测试且不易损坏(如果您更改了源元素的名称 IsDeadToggle,那么您需要记住更新绑定(bind)目标)。

关于c# - 使用 StackPanel 包围控件时出现元素名称绑定(bind)错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23113166/

相关文章:

c# - REST 标准 - 输出模型是否应该始终匹配输入模型?

c# - 使用 HttpClient 上传多部分表单文件

wpf - 将数据传递给 mvvm 用户控件

wpf按钮背景图片

wpf - Silverlight 和 WPF 使用哪些度量单位?

wpf - 具有单选和单击取消选择的列表框...?

c# - Windows Phone 8.1 应用程序上的双向绑定(bind),使用 MVVM

c# - 在 OpenXML 中创建具有变量列的表

c# - 带有方法重载和枚举的奇怪(可能是错误的?)C# 编译器行为

c# - 上下文菜单中的命令不起作用