Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 为什么不是';绑定到依赖项属性时是否设置了依赖项属性?_.net_Wpf_Dependency Properties - Fatal编程技术网

.net 为什么不是';绑定到依赖项属性时是否设置了依赖项属性?

.net 为什么不是';绑定到依赖项属性时是否设置了依赖项属性?,.net,wpf,dependency-properties,.net,Wpf,Dependency Properties,我的WPF应用程序中显示了两个集合,我希望其中一个集合中的元素在另一个集合中被禁用。为此,我创建了一个继承ListBox的自定义控件FilteringListBox,并希望在其中添加一些处理,以禁用通过FilteringListBox上的属性在集合集中设置的元素。现在,我的问题是没有设置获取我要从中筛选元素的ObservableCollection的dependency属性——即使我在xaml中绑定了它 我已经创建了一个简化的应用程序,在这里我重现了这个问题。这是我的Xaml: <Stac

我的WPF应用程序中显示了两个集合,我希望其中一个集合中的元素在另一个集合中被禁用。为此,我创建了一个继承ListBox的自定义控件FilteringListBox,并希望在其中添加一些处理,以禁用通过FilteringListBox上的属性在集合集中设置的元素。现在,我的问题是没有设置获取我要从中筛选元素的ObservableCollection的dependency属性——即使我在xaml中绑定了它

我已经创建了一个简化的应用程序,在这里我重现了这个问题。这是我的Xaml:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <StackPanel Orientation="Vertical">
            <TextBlock>Included</TextBlock>
            <ListBox x:Name="IncludedFooList" ItemsSource="{Binding IncludedFoos}"></ListBox>
        </StackPanel>
        <Button Margin="10" Click="Button_Click">Add selected</Button>
        <StackPanel Orientation="Vertical">
            <TextBlock>Available</TextBlock>
            <Listbox:FilteringListBox x:Name="AvailableFooList" ItemsSource="{Binding AvailableFoos}" FilteringCollection="{Binding IncludedFoos}"></Listbox:FilteringListBox>
        </StackPanel>                
    </StackPanel>            
</StackPanel>

包括
添加选定的
可用
这是我的自定义组件-当前仅包含Dependency属性:

public class FilteringListBox : ListBox
{
    public static readonly DependencyProperty FilteringCollectionProperty =
        DependencyProperty.Register("FilteringCollection", typeof(ObservableCollection<Foo>), typeof(FilteringListBox));                                                 

    public ObservableCollection<Foo> FilteringCollection
    {
        get
        {
            return (ObservableCollection<Foo>)GetValue(FilteringCollectionProperty);
        }
        set
        {
            SetValue(FilteringCollectionProperty, value);
        }
    }
}
公共类过滤器glistbox:ListBox
{
公共静态只读从属属性FilteringCollectionProperty=
DependencyProperty.Register(“FilteringCollection”、typeof(ObservableCollection)、typeof(FilteringListBox));
公共可见收集筛选器收集
{
得到
{
返回(ObservableCollection)GetValue(FilteringCollectionProperty);
}
设置
{
SetValue(FilteringCollectionProperty,值);
}
}
}
对于完整的代码,代码隐藏和类定义如下:

public partial class MainWindow : Window
{
    private MainViewModel _vm;

    public MainWindow()
    {
        InitializeComponent();
        _vm = new MainViewModel();
        DataContext = _vm;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (AvailableFooList.SelectedItem == null)
            return;
        var selectedFoo = AvailableFooList.SelectedItem as Foo;
        _vm.IncludedFoos.Add(selectedFoo);
    }
}

public class MainViewModel
{
    public MainViewModel()
    {
        IncludedFoos = new ObservableCollection<Foo>();
        AvailableFoos = new ObservableCollection<Foo>();
        GenerateAvailableFoos(); 
    }

    private void GenerateAvailableFoos()
    {
        AvailableFoos.Add(new Foo { Text = "Number1" });
        AvailableFoos.Add(new Foo { Text = "Number2" });
        AvailableFoos.Add(new Foo { Text = "Number3" });
        AvailableFoos.Add(new Foo { Text = "Number4" });
    }

    public ObservableCollection<Foo> IncludedFoos { get; set; }
    public ObservableCollection<Foo> AvailableFoos { get; set; }
}

public class Foo
{
    public string Text { get; set; }
    public override string ToString()
    {
        return Text;
    }
}
公共部分类主窗口:窗口
{
私有MainViewModel_vm;
公共主窗口()
{
初始化组件();
_vm=新的MainViewModel();
数据上下文=_vm;
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
if(AvailableFolist.SelectedItem==null)
返回;
var selectedFoo=AvailableFooList.SelectedItem作为Foo;
_vm.IncludedFoos.Add(selectedFoo);
}
}
公共类主视图模型
{
公共主视图模型()
{
IncludedFoos=新的ObservableCollection();
AvailableFoos=新的ObservableCollection();
GenerateAvailableFoos();
}
私有void GenerateAvailableFoos()
{
Add(newfoo{Text=“Number1”});
Add(newfoo{Text=“Number2”});
Add(newfoo{Text=“Number3”});
Add(newfoo{Text=“Number4”});
}
公共ObservableCollection IncludedFoos{get;set;}
公共ObservableCollection可用OS{get;set;}
}
公开课Foo
{
公共字符串文本{get;set;}
公共重写字符串ToString()
{
返回文本;
}
}

我将断点添加到FilteringListBox中DependencyProperty FilteringCollection的setter和getter,但它从未被触发。为什么?我怎样才能修好它

绑定系统绕过依赖属性的set和get访问器。如果要在依赖项属性更改时执行代码,则应将
PropertyChangedCallback
添加到
dependencProperty
定义中。

MSDN有一节关于,您需要注册

来自msdn的示例

public static readonly DependencyProperty AquariumGraphicProperty 
= DependencyProperty.Register(
  "AquariumGraphic",
  typeof(Uri),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(null,
      FrameworkPropertyMetadataOptions.AffectsRender, 
      new PropertyChangedCallback(OnUriChanged)
  )
);

private static void OnUriChanged(DependencyObject d, 
                                 DependencyPropertyChangedEventArgs e) {
  Shape sh = (Shape) d;
  sh.Fill = new ImageBrush(new BitmapImage((Uri)e.NewValue));
}

WPF框架从不直接使用get和set属性。你提供它们只是为了方便自己。相反,您需要向依赖项属性注册添加回调。当值绑定到依赖项属性时,将调用回调。因此,
FilteredListBox
的代码应更改为类似于以下内容:

public partial class FilteringListBox : ListBox
{
    public static readonly DependencyProperty FilteringCollectionProperty =
        DependencyProperty.Register("FilteringCollection", typeof(ObservableCollection<Foo>), typeof(FilteringListBox), 
        new PropertyMetadata(null, FilteringCollectionPropertyCallback));

    static void FilteringCollectionPropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        FilteringListBox listbox = d as FilteringListBox;
        // Do some work here
    }

    public ObservableCollection<Foo> FilteringCollection
    {
        get
        {
            return (ObservableCollection<Foo>) GetValue(FilteringCollectionProperty);
        }
        set
        {
            SetValue(FilteringCollectionProperty, value);
        }
    }
}
public分部类过滤器glistbox:ListBox
{
公共静态只读从属属性FilteringCollectionProperty=
从属属性寄存器(“FilteringCollection”、typeof(ObservableCollection)、typeof(FilteringListBox),
新的PropertyMetadata(null,FilteringCollectionPropertyCallback));
静态void FilteringCollectionPropertyCallback(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
FilteringListBox listbox=d作为FilteringListBox;
//在这里做些工作
}
公共可见收集筛选器收集
{
得到
{
返回(ObservableCollection)GetValue(FilteringCollectionProperty);
}
设置
{
SetValue(FilteringCollectionProperty,值);
}
}
}

您是否意识到默认值是静态保留的,在本例中,默认值是通过引用使用的?默认情况下,每个FilteringListBox都将引用同一个ObservableCollection实例,除非该值被覆盖。这一点很好。在这种情况下,默认值是不必要的。它正被viewmodel的绑定覆盖。+1。我希望它更简单。。。一些更好的约定来创建从属属性。。。但这是我们必须接受的。getter/setter对开发人员来说只是一种方便,但对数据绑定没有任何意义。其实情况正好相反。绑定系统调用
GetValue
SetValue
,而属性只是在不绑定的情况下执行。调用
SetValue
时触发该事件。太糟糕了,太令人困惑了。嗯。。不是很直观,也不方便,但这就解决了问题。谢谢