4

我正在创建一个简单的用户控件,将弹出窗口与文本视图相结合,这并不疯狂。当我一开始在窗口中设置它以设置样式时,它工作得很好,但是当我将它移到用户控件中以实际完成它时,它就不能再正常工作了。

我将一个最小值和最大值传递给控件,​​然后它会自动创建一个数字列表以在该范围内进行选择。在用户控件中,数字列表没有正确绑定,谁知道为什么。也许有人可以看看我的代码。

我已经阅读了很多关于此的其他问题,但真的不知道发生了什么。我的输出窗口中没有任何错误,所以那里没有任何线索。无论如何,这是代码 -

用户控件.xaml

<UserControl x:Class="UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Name="Me"
         DataContext="{Binding RelativeSource={RelativeSource Self}}">

<StackPanel>
    <TextBox Name="myTextbox"
             Height="30"
             Margin="0"
             FontSize="14"
             IsReadOnly="True"
             Padding="5,2"
             Text="{Binding Value}" />
    <Popup x:Name="myPopup"
           PlacementTarget="{Binding ElementName=myTextbox}"
           StaysOpen="True">
        <Popup.Style>
            <Style TargetType="{x:Type Popup}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=myTextbox, Path=IsFocused}" Value="True">
                        <Setter Property="IsOpen" Value="True" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Popup.Style>

        <StackPanel>
            <ListView Name="myListView"
                      Height="100"
                      MaxHeight="300"
                      ItemsSource="{Binding List,
                                            UpdateSourceTrigger=PropertyChanged}"
                      SelectionChanged="ListView_SelectionChanged">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Label Width="100"
                               Height="30"
                               Margin="0"
                               Content="{Binding}"
                               FontFamily="Segoe UI"
                               FontSize="14"
                               Padding="5,2" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button Width="200" Height="30" />
        </StackPanel>
    </Popup>

</StackPanel>

用户控件.xaml.vb

Imports System.ComponentModel
Imports System.Linq.Expressions
Imports System.Collections.ObjectModel

Class UserControl1

' Dependency Properties
Public Shared ReadOnly ListProperty As DependencyProperty = DependencyProperty.Register("List", GetType(ObservableCollection(Of Integer)), GetType(MainWindow))
Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(Integer), GetType(MainWindow))
Public Shared ReadOnly MaxValueProperty As DependencyProperty = DependencyProperty.Register("MaxValue", GetType(Integer), GetType(MainWindow))
Public Shared ReadOnly MinValueProperty As DependencyProperty = DependencyProperty.Register("MinValue", GetType(Integer), GetType(MainWindow))

' Properties
Public Property List As ObservableCollection(Of Integer)
    Get
        Return DirectCast(GetValue(ListProperty), ObservableCollection(Of Integer))
    End Get
    Set(value As ObservableCollection(Of Integer))
        SetValue(ListProperty, value)
    End Set
End Property

Public Property Value As Integer
    Get
        Return DirectCast(GetValue(ValueProperty), Integer)
    End Get
    Set(value As Integer)
        SetValue(ValueProperty, value)

    End Set
End Property

Public Property MaxValue As Integer
    Get
        Return DirectCast(GetValue(MaxValueProperty), Integer)
    End Get
    Set(value As Integer)
        SetValue(MaxValueProperty, value)
    End Set
End Property

Public Property MinValue As Integer
    Get
        Return DirectCast(GetValue(MinValueProperty), Integer)
    End Get
    Set(value As Integer)
        SetValue(MinValueProperty, value)
    End Set
End Property

Private Sub ListView_SelectionChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs)
    Value = List(myListView.SelectedIndex)
End Sub

Private Sub UserControl1_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    List = New ObservableCollection(Of Integer)

    ' Add all available numbers into the list
    For iCounter As Integer = MinValue To MaxValue
        List.Add(iCounter)
    Next

    ' Set the selected index on the list for the value
    myListView.SelectedIndex = Value - MinValue
End Sub
End Class

仅供参考,当我对此进行测试时,我自己在窗口和用户控件设置中设置了最小值和最大值。

4

3 回答 3

17

我认为您犯了与我刚开始学习 WPF 时相同的错误。我不能保证这你的问题的原因,但因为这是我能看到的唯一一个,我会解决它。不幸的是,有很多糟糕的教程和快速示例展示了 aUserControl.DataContext与自身的连接:

DataContext="{Binding RelativeSource={RelativeSource Self}}"

或者:

DataContext = this;

现在,如果您不想连接到外部,这是完全可以接受Bind因为UserControl它是连接后面代码中定义的属性的一种快速简便的方法。但是,当您想Bind从控件外部访问属性时,您会发现问题。在这些情况下(如果不是在所有情况下),您应该使用RelativeSource BindingtoBind到您的代码后面的属性:

<TextBox Name="myTextbox" Height="30" Margin="0" FontSize="14" IsReadOnly="True"
    Padding="5,2" Text="{Binding Value, RelativeSource={RelativeSource AncestorType={
    x:Type UserControl1}}}" />

在 thisBinding中,UserControl1UserControl声明属性的名称。这应该在所有内部Bindings 上完成。这样,DataContext没有设置为,但s仍然可以找到属性。UserControlBinding

RelativeSource您可以从 MSDN 上的RelativeSource MarkupExtension页面了解更多信息。

于 2013-10-05T14:50:53.480 回答
9

由于我无法向 Sheridan 提供好的答案,我必须提供一个新的答案,对此感到抱歉。

虽然我喜欢这个解决方案

DataContext="{Binding RelativeSource={RelativeSource Self}}"

它很快就失败了(正如谢里登已经指出的那样)。

您可以做的只是设置用户控件内容的 DataContext

<UserControl x:Class="Example.View.Controls.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:controls="clr-namespace:Example.View.Controls"
         mc:Ignorable="d">
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:MyUserControl}}}">

</Grid>

这样,所有以下绑定都具有较少的样板代码,因为您可以直接从代码隐藏中绑定到您的 DP,例如:

<Label Content="{Binding MyLabel}"/>
于 2014-12-11T18:12:37.260 回答
1

至于Windows 应用程序(Windows 8 和 Windows 10 UWP),方法是为您的控件命名并使用PathElementName在您的 XAML 文件中引用它:

<UserControl
x:Class="MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="Control"
mc:Ignorable="d" >

   <Grid Height="240" VerticalAlignment="Top">
     <Rectangle Fill="{Binding ElementName=Control, Path=Background}" />
   </Grid>
</UserControl>

``

于 2015-11-11T13:43:24.187 回答