Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.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
C# 在WPF中使用数据绑定刷新UI_C#_Wpf_Data Binding - Fatal编程技术网

C# 在WPF中使用数据绑定刷新UI

C# 在WPF中使用数据绑定刷新UI,c#,wpf,data-binding,C#,Wpf,Data Binding,我有一个三层深的树景 -MAIN ->:SUB1 >:SUB2 >:SUB2 -X:SUB1 X:SUB2 SUB1 SUB1 -主要 ->:SUB1 >:SUB2 >:SUB2 -X:SUB1 X:SUB2 SUB1 SUB1 其中,>和X表示表示表示该特定项目状态的图形(从后端确定) 我正在使用一个可观察字典绑定到此树(它有一个ICollectionChanged事件)。结构如下: ObservableDictionary<string,CustomClas

我有一个三层深的树景

-MAIN ->:SUB1 >:SUB2 >:SUB2 -X:SUB1 X:SUB2 SUB1 SUB1 -主要 ->:SUB1 >:SUB2 >:SUB2 -X:SUB1 X:SUB2 SUB1 SUB1 其中,>和X表示表示表示该特定项目状态的图形(从后端确定)

我正在使用一个可观察字典绑定到此树(它有一个ICollectionChanged事件)。结构如下:


ObservableDictionary<string,CustomClass> mainitems;

public class CustomClass{
    ObservableDictionary<string, InnerClass> sub1item;
    // Bunch of properties and methods in this class
    // INotify not implemented
}

public class InnerClass{
    // Bunch of properties and methods in this class
    // INotify not implemented
    public SomeEnum Status{
        get{ return this.status; }
    }
}
public class InnerClass: INotifyPropertyChanged
{
     private string _propertyName;

     //Implemented from INotifyPropertyChanged
     public event PropertyChangedEventHandler PropertyChanged;

     public string PropertyName
     {
        get { return _propertyName; }
        set 
        { 
              _propertyName = value;
              OnPropertyChanged("Name or Property Data"); 
        }
     }

     //Just using string as an example, send whatever data you'd like
     protected void PropertyChanged(string name)
     {
        //Check to make sure the event is wired.
        if(PropertyChanged != null)
        {
              //Fire event
              PropertyChanged(this, name);
        }
     }
}

可观察的主要项目;
公共类CustomClass{
观察医学分项;
//该类中的一组属性和方法
//INotify没有实现
}
公共类内部类{
//该类中的一组属性和方法
//INotify没有实现
公共枚举状态{
获取{返回this.status;}
}
}
上面提到的图形是使用自定义转换器绑定的,该转换器将状态枚举转换为路径,以便可以绑定(即)

问题:

我的问题是,当我用新状态更新CustomClass的sub1item字典时,它不会在UI中更新它。我认为实现INotify可能会起作用,但我不知道我需要在哪里更新它,以及具体如何更新

编辑: 我的treeview的XAML模板如下所示:


<TreeView Name="tvInstance" ItemsSource="{Binding}" TreeViewItem.Selected="tviSelected" IsTextSearchEnabled="True">
    <TreeView.ItemContainerStyle>
        <Style>
            <Setter Property="TreeViewItem.IsExpanded" Value="{Binding Path=Value.Expanded, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Path=Value.CustomClass}" ItemContainerStyle="{x:Null}">
                <StackPanel Orientation="Horizontal">
                <Label Content="{Binding Path=Key}"/>
            </StackPanel>
            <HierarchicalDataTemplate.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=Value.AnotherClass}">
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Path=Value.Status, Converter={StaticResource convertstatus} }"
                            Width="10" Height="10"/>
                        <Label Content="{Binding Path=Key}" />
                    </StackPanel>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="{Binding Path=Value, Converter={StaticResource convertstatus} }"
                            Width="10" Height="10"/>
                                <Label Content="{Binding Path=Key}" />
                            </StackPanel>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

编辑:在我的Main类、CustomClass和InnerClass中添加所有INotifyProperty事件后,它仍然不起作用。我使用的是Dr.WPF版本的Observatedictionary(使用字典对我的应用程序至关重要,因为我需要进行大量查找)。救命啊

后记 此页面中的答案是正确的,因为INotifyPropertyChanged需要在我希望在UI中更新的属性上实现

我发现装订这本词典太麻烦了,所以我保存了一本可观察的集和一本词典。我使用字典进行查找,使用集合进行绑定(因为两者都使用对对象的相同引用,所以使用集合和唯一的O(n)操作很容易删除)


关于UI中的更新,请参阅本页的其他帖子。

这可能有点长,以下是我的最佳猜测:

public class CustomClass : INotifyPropertyChanged
{
  public CustomClass()
  {
    sub1item = new ObservableDictionary<string, InnerClass>();
    // This next line may not be necessary... Changes might propogate up.
    sub1item.CollectionChanged += () => NotifyPropertyChange("Sub1Item");
  }

  private ObservableDictionary<string, InnerClass> sub1item;
  public ObservableDictionary<string, InnerClass> Sub1Item
  {
    get { return sub1item; }
    private set { sub1item = value; NotifyPropertyChange("Sub1Item"); }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void NotifyPropertyChanged(String info)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
  }
}

public class InnerClass : INotifyPropertyChanged
{
  public SomeEnum Status
  {
    get { return this.status; }
    private set { this.status = value; NotifyPropertyChange("Status"); }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void NotifyPropertyChanged(String info)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
  }
}
公共类CustomClass:INotifyPropertyChanged
{
公共自定义类()
{
sub1item=新的可观察药物();
//下一行可能没有必要…可能会出现更改。
sub1item.CollectionChanged+=()=>NotifyPropertyChange(“sub1item”);
}
私人医疗子项目;
公共医疗子项目
{
获取{return sub1item;}
私有集{sub1item=value;NotifyPropertyChange(“sub1item”);}
}
公共事件属性更改事件处理程序属性更改;
私有void NotifyPropertyChanged(字符串信息)
{
if(PropertyChanged!=null)
{
PropertyChanged(此,新PropertyChangedEventArgs(信息));
}
}
}
公共类InnerClass:INotifyPropertyChanged
{
公共枚举状态
{
获取{返回this.status;}
私有集{this.status=value;NotifyPropertyChange(“status”);}
}
公共事件属性更改事件处理程序属性更改;
私有void NotifyPropertyChanged(字符串信息)
{
if(PropertyChanged!=null)
{
PropertyChanged(此,新PropertyChangedEventArgs(信息));
}
}
}
只要确保通过调用status=something来更新状态,而不是直接通过this.status

编辑:如果您只想更新获得更新状态的单个对象,我不确定这样做是否可行。我怀疑这将表明Sub1Item已更改,但mainitems可能不知道单个对象。这取决于您的实现

如果您为CustomClass创建了一个DataTemplate,该DataTemplate绑定到Sub1Item,那么您的绑定将仅正确更新更新状态

<DataTemplate DataType="{x:Type myClrNamespace:InnerClass}">
    <Grid>
        <TextBlock Text={Binding Path=Status}/>
    </Grid>
</DataTemplate>
...
<ListBox x:Name="listStatus"/>

...

然后在C#某处,您可以有:
listStatus=mainlist[0]在看到您的TreeView ItemTemplate示例后,我再也不确定了。

您需要使用一个事件,让您的类实现INotifyPropertyChanged,它将如下所示:


ObservableDictionary<string,CustomClass> mainitems;

public class CustomClass{
    ObservableDictionary<string, InnerClass> sub1item;
    // Bunch of properties and methods in this class
    // INotify not implemented
}

public class InnerClass{
    // Bunch of properties and methods in this class
    // INotify not implemented
    public SomeEnum Status{
        get{ return this.status; }
    }
}
public class InnerClass: INotifyPropertyChanged
{
     private string _propertyName;

     //Implemented from INotifyPropertyChanged
     public event PropertyChangedEventHandler PropertyChanged;

     public string PropertyName
     {
        get { return _propertyName; }
        set 
        { 
              _propertyName = value;
              OnPropertyChanged("Name or Property Data"); 
        }
     }

     //Just using string as an example, send whatever data you'd like
     protected void PropertyChanged(string name)
     {
        //Check to make sure the event is wired.
        if(PropertyChanged != null)
        {
              //Fire event
              PropertyChanged(this, name);
        }
     }
}

基本上,让这些事件为您的子项激发,并传递给CustomClass对象。然后,如果需要,让CustomClass处理这些事件,并向主对象激发另一个事件,告诉它更新UI

可观察集合实现
INofityCollectionChanged
,WPF使用该集合刷新视图项集合

但是,要更新状态,您需要数据来实现
INotifyPropertyChanged

  • 要显示在视图中的每个类都必须实现它,这样WPF就可以知道它的属性何时更改以及它的哪些属性已更改
实现很简单

// Should implement INotifyPropertyChanged if the dictionary itself
// can be changed and not only its items
public class CustomClass {
    ObservableDictionary sub1item;
    // Bunch of properties and methods in this class
    // INotify not implemented
}


public class InnerClass : INotifyProperyChanged {
    // Bunch of properties and methods in this class
    // INotify not implemented
    public SomeEnum Status{
        get{ return this.status; }
    }

    public event PropertyChangedEventHandler PropertyChanged;



protected void NotifyPropertyChanged(string propertyName)
{
    if(PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}


// where ever this.status is changed directly,
// call NotifyPropertyChanged("Status")
// (at end of that method)
//
// if this.status is changed from outside class (if public),
// then add a public method NotifyStatusChanged() which calls
// NotifyPropertyChanged("Status")
//
// If Status property has a set{} then if new value != this.status,
// call NotifyPropertyChanged("Status") at end of setter

}
-VB.NET

一般功能列表:

  • 可观测的(TKey、TValue的)
  • AddRange只收到一次通知
  • 通用事件参数(属于TKey、TValue)
  • NotifyDictionaryChangeg(TKey,TValue)——CancelEventArgs的一个子类,允许取消操作

类型为“任务”的类的工作示例

公共类任务:INotifyPropertyChanged

{

    //Implemented from INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
私有字符串文本

    public string Text
    {
        get { return text; }
        set { 
            text = value;
            NotifyPropertyChanged("Text");

            }
    }
}

另一方面,值得注意的是,当数据绑定到类型集合时,需要使用ObservableCollection而不是than List来获取动态更新的ItemSource。列表