【问题标题】:Element Name Binding Error when surrounding controls with StackPanel使用 StackPanel 包围控件时出现元素名称绑定错误
【发布时间】:2014-04-16 15:01:16
【问题描述】:

XAMLElement Name 的绑定遇到了一个奇怪的问题。

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

我将两个用户控件的可见性与两个切换按钮(IsDeadToggle 和 IsNotTransportable)的 IsChecked 属性绑定并使用 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,它会再次起作用...我开始认为这是一个深度问题。但我不明白为什么我的绑定在特定深度级别上不起作用

编辑 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-->

【问题讨论】:

  • 不确定这是否会有所不同,但您是否尝试过使用 Name 而不是 x:name?我读过有一些差异。
  • 基本上我会说问题出在可视树上。查看此链接:stackoverflow.com/questions/705853/…
  • @sexta13 控件不在DataTemplate/ControlTemplate
  • @kenjara 尝试替换 x:name 但没有成功

标签: c# wpf xaml binding


【解决方案1】:

我可以看到您的ToggleButtonIsDeadToggleIsChecked 属性上与您的数据上下文中的Add.Presenter.Customer.IsAlive 属性有两种方式绑定。

我还可以看到您正在尝试将您的LabelDatePickerVisibility 属性绑定到ToggleButtonIsChecked 属性,使用转换器进行反转,然后将布尔值转换为@987654330 @。

由于ToggleButtonLabelDatePicker 共享相同的数据上下文,我只需将LabelDatePicker 的可见性绑定到数据上下文的相同属性:

<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.INotifyPropertyChangedIsAlive 属性需要使用属性名称引发PropertyChanged 事件,以确保LabelDatePicker 正确当IsDeadToggle 复选框更改其值时通知重新绑定。

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

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

【讨论】:

  • 谢谢!!那成功了!将来我会尽可能多地绑定到 datacontext 中的道具。但是,我不明白为什么 ElementName 不能在特定的深度级别上工作,但我同意使用 DataContext 更容易阅读......
猜你喜欢
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 2023-03-13
  • 2011-07-31
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多