代码之家  ›  专栏  ›  技术社区  ›  xandy

绑定在代码隐藏中定义的对象

  •  78
  • xandy  · 技术社区  · 15 年前

    我有一些在代码隐藏中实例化的对象,例如,XAML称为window.xaml,在window.xaml.cs中。

    protected Dictionary<string, myClass> myDictionary;
    

    如何仅使用XAML标记将此对象绑定到(例如)列表视图?

    更新:

    (这正是我的测试代码中的内容):

    <Window x:Class="QuizBee.Host.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="{Binding windowname}" Height="300" Width="300"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
        <Grid>
        </Grid>
    </Window>
    

    在代码隐藏中

    public partial class Window1 : Window
    {
        public const string windowname = "ABCDEFG";
    
        public Window1()
        {
            InitializeComponent();
        }
    }
    

    假设标题应该变成“abcdefg”对吗?但最后却什么也没显示。

    10 回复  |  直到 7 年前
        1
  •  93
  •   Ryogi Guy Starbuck    8 年前

    可以为控件、窗体等设置DataContext,如下所示:

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

    澄清 :

    要设置为上面的值的数据上下文应该在“拥有”后面代码的任何元素上完成——所以对于一个窗口,应该在窗口声明中设置它。

    我举了一个使用此代码的示例:

    <Window x:Class="MyClass"
      Title="{Binding windowname}"
      DataContext="{Binding RelativeSource={RelativeSource Self}}"
      Height="470" Width="626">
    

    然后,此级别的DataContext集由窗口中的任何元素继承(除非您显式地为子元素更改它),因此在为窗口设置了DataContext之后,您应该能够直接绑定到codebehind。 属性 从窗口上的任何控件。

        2
  •  116
  •   Saad Imran.    14 年前

    有一种更简单的方法可以做到这一点。可以为窗口或用户控件指定一个名称,然后按elementname绑定。

    Windows 1.xAML

    <Window x:Class="QuizBee.Host.Window1"
            x:Name="Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
        <ListView ItemsSource="{Binding ElementName=Window1, Path=myDictionary}" />
    </Window>
    

    窗口1.xaml.cs

    public partial class Window1:Window
    {
        // the property must be public, and it must have a getter & setter
        public Dictionary<string, myClass> myDictionary { get; set; }
    
        public Window1()
        {
            // define the dictionary items in the constructor
            // do the defining BEFORE the InitializeComponent();
    
            myDictionary = new Dictionary<string, myClass>()
            {
                {"item 1", new myClass(1)},
                {"item 2", new myClass(2)},
                {"item 3", new myClass(3)},
                {"item 4", new myClass(4)},
                {"item 5", new myClass(5)},
            }; 
    
            InitializeComponent();
        }
    }
    
        3
  •  23
  •   CatBusStop    14 年前

    虽然Guy的答案是正确的(可能是10个案例中的9个),但值得注意的是,如果您试图从已经设置了其DataContext的控件中执行此操作,那么当您将DataContext设置回自身时,您将重置此操作:

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

    这当然会破坏现有的绑定。

    如果是这种情况,您应该在试图绑定的控件上设置RelativeSource,而不是它的父控件。

    即,对于绑定到用户控件的属性:

    Binding Path=PropertyName, 
            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}
    

    考虑到目前查看数据绑定的进展有多困难,即使您找到了该设置,也应该记住这一点。 RelativeSource={RelativeSource Self} 目前正在工作:)

        4
  •  5
  •   jondinham    12 年前

    再澄清一下: 没有“get”、“set”的属性将无法绑定

    我正像询问者一样面对这个案子。我必须具备以下条件才能使绑定正常工作:

    //(1) Declare a property with 'get','set' in code behind
    public partial class my_class:Window {
      public String My_Property { get; set; }
      ...
    
    //(2) Initialise the property in constructor of code behind
    public partial class my_class:Window {
      ...
      public my_class() {
         My_Property = "my-string-value";
         InitializeComponent();
      }
    
    //(3) Set data context in window xaml and specify a binding
    <Window ...
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
      <TextBlock Text="{Binding My_Property}"/>
    </Window>
    
        5
  •  1
  •   Phillip Ngan    15 年前

    定义转换器:

    public class RowIndexConverter : IValueConverter
    {
        public object Convert( object value, Type targetType,
                               object parameter, CultureInfo culture )
        {
            var row = (IDictionary<string, object>) value;
            var key = (string) parameter;
            return row.Keys.Contains( key ) ? row[ key ] : null;
        }
    
        public object ConvertBack( object value, Type targetType,
                                   object parameter, CultureInfo culture )
        {
            throw new NotImplementedException( );
        }
    }
    

    绑定到字典的自定义定义。我省略了很多重写,但索引器是重要的,因为它在值更改时发出属性更改事件。这是源到目标绑定所必需的。

    public class BindableRow : INotifyPropertyChanged, IDictionary<string, object>
    {
        private Dictionary<string, object> _data = new Dictionary<string, object>( );
    
        public object Dummy   // Provides a dummy property for the column to bind to
        {
            get
            {
                return this;
            }
            set
            {
                var o = value;
            }
        }
    
    
        public object this[ string index ]
        {
            get
            {
                return _data[ index ];
            }
            set
            {
                _data[ index ] = value;
                InvokePropertyChanged( new PropertyChangedEventArgs( "Dummy" ) ); // Trigger update
            }
        }
    
    
    }
    

    在.xaml文件中使用此转换器。第一个参考:

    <UserControl.Resources>
        <ViewModelHelpers:RowIndexConverter x:Key="RowIndexConverter"/>
    </UserControl.Resources>
    

    例如,如果您的字典中有一个键为“name”的条目,那么要绑定到它:使用

    <TextBlock  Text="{Binding Dummy, Converter={StaticResource RowIndexConverter}, ConverterParameter=Name}">
    
        6
  •  1
  •   viky    15 年前

    将您的属性“windowname”设置为dependencyproperty,并保持其余属性不变。

        7
  •  0
  •   Szymon Rozga    15 年前

    在代码隐藏中,将窗口的DataContext设置为字典。在XAML中,您可以编写:

    <ListView ItemsSource="{Binding}" />
    

    这将把ListView绑定到字典。

    对于更复杂的场景,这将是 MVVM 模式。

        8
  •  0
  •   Partial    15 年前

    一种方法是创建一个ObservableCollection(system.collections.objectmodel)并将字典数据放在其中。然后您应该能够将ObservableCollection绑定到您的列表框。

    在XAML中,您应该具有如下内容:

    <ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" />
    
        9
  •  0
  •   davesbrain    13 年前

    我也有同样的问题,但我的问题不是因为我设置了一个局部变量…我当时在一个子窗口中,需要设置一个相对的数据上下文,我刚将其添加到窗口XAML中。

    <Window x:Class="Log4Net_Viewer.LogItemWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="LogItemWindow" Height="397" Width="572">
    
        10
  •  0
  •   Николай Солдаткин    7 年前

    你可以试试x:参考技巧

    <Window ... x:Name="myWindow"><ListBox ItemsSource="{Binding Items, Source={x:Reference myWindow}}" /></Window>