[英](WPF) XamDataGrid + Hierarchical + Load on Demand + Dynamic Columns
我正在使用XamDataGrid並且需要每一行都是分層的(有幾個子節點也是分層的)。 它必須按需加載其數據,並根據我正在查詢的服務器返回的結果具有動態子列。
快進一點:
我已經開始使用ITypedList和ICustomPropertyDescriptor來動態添加/刪除屬性,以便可以操作相應的列。 無濟於事。
我嘗試在后面的代碼中動態更改FieldLayouts,用於由ParentFieldLayoutKey指定的每個特定層次結構。 但是,如果我修改了我的任何字段布局,它會直觀地將更改應用於所有字段布局,但在后面的代碼中,實際上只修改了所選的字段布局。 為什么我不能在不改變所有FieldLayout的情況下修改它們?
我還嘗試使用包含具有關系的表的DataSet來建立所需的層次結構,但是這樣做到目前為止還無法按需加載數據。 除非有某種方法可以做到這一點,否則我無法在infragistics docs中的任何地方找到它?
這是我的要求:
問題:
編輯:是的。 這是可能的。
這是我的版本。 這基本上可以滿足您的需求。 在子fieldlayout中,動態添加列並相應地執行數據綁定
楷模:
public class Country
{
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
public ObservableCollection<State> States { get; set; }
}
public class State
{
private readonly Dictionary<string, object> _info = new Dictionary<string, object>();
/// <summary>
/// Attributes of the state can be added dynamically (key will be the attribtue name etc...)
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object this[string key]
{
get
{
return this._info[key];
}
set
{
this._info[key] = value;
}
}
public string StateName { get; set; }
}
行為:
public class GridFieldLayoutBehaviour : Behavior<XamDataGrid>
{
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.FieldLayoutInitialized += OnFieldLayoutInitialized;
this.AssociatedObject.RecordExpanded += OnRecordExpanded;
}
void OnRecordExpanded(object sender, Infragistics.Windows.DataPresenter.Events.RecordExpandedEventArgs e)
{
((ViewModel)this.AssociatedObject.DataContext).AddStateAttributes();
}
void OnFieldLayoutInitialized(object sender, Infragistics.Windows.DataPresenter.Events.FieldLayoutInitializedEventArgs e)
{
if( e.FieldLayout.ParentFieldName == "States")
{
((ViewModel)this.AssociatedObject.DataContext).GridFieldLayout = e.FieldLayout;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.FieldLayoutInitialized -= OnFieldLayoutInitialized;
this.AssociatedObject.RecordExpanded -= OnRecordExpanded;
}
}
視圖模型:
public class ViewModel
{
#region Private Fields
private readonly ObservableCollection<Country> _countries = new ObservableCollection<Country>();
private readonly List<string> _stateTotalAttributes = new List<string>();
#endregion
public ViewModel()
{
FillData();
var stateAttributes = new string[] {"Population", "Unemployment Rate", "Capital", "Governor", "TimeZone", "Area"};
foreach (var stateAttribute in stateAttributes)
_stateTotalAttributes.Add(stateAttribute);
}
public ObservableCollection<Country> Countries
{
get { return this._countries; }
}
public FieldLayout GridFieldLayout { get; set; }
/// <summary>
/// Country and the states are populated
/// </summary>
private void FillData()
{
var country = new Country();
country.States = new ObservableCollection<State>();
country.Name = "USA";
var xdoc = XDocument.Load("states_data.xml");
foreach (var state in xdoc.Descendants("states").Descendants())
{
var newState = new State();
newState.StateName = state.Attributes("name").FirstOrDefault().Value;
newState["Unemployment Rate"] = state.Attributes("unemployment-rate").FirstOrDefault().Value;
newState["Capital"] = state.Attributes("capital").FirstOrDefault().Value;
newState["Governor"] = state.Attributes("governor").FirstOrDefault().Value;
newState["Area"] = state.Attributes("area").FirstOrDefault().Value;
newState["TimeZone"] = state.Attributes("timezone").FirstOrDefault().Value;
newState["Population"] = state.Attributes("population").FirstOrDefault().Value;
country.States.Add(newState);
}
_countries.Add(country);
}
public void AddStateAttributes()
{
GridFieldLayout.Fields.BeginUpdate();
// Remove the current columns (except for StateName)
var removableFields = GridFieldLayout.Fields.Where(f => f.Name != "StateName");
removableFields.ToList().ForEach(field => GridFieldLayout.Fields.Remove(field));
// Figure out what state attributes to add
var random = new Random(DateTime.Now.Millisecond);
var numCols = random.Next(1, 6);
var colsToAdd = GetStateAttributes(numCols, random);
// Finally add the new ones'
foreach (var col in colsToAdd)
{
var field = new UnboundField();
field.Name = col;
field.Binding = new Binding()
{
Mode = BindingMode.TwoWay,
Path = new PropertyPath(string.Format("[{0}]", col)),
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
GridFieldLayout.Fields.Add(field);
}
GridFieldLayout.Fields.EndUpdate();
}
private List<string> GetStateAttributes(int numCols, Random random)
{
List<string> colsToAdd = new List<string>();
for( int i = 0; i < numCols; i++)
{
int idx = random.Next(1, 6) - 1;
if(colsToAdd.Contains(_stateTotalAttributes[idx]) == false)
{
colsToAdd.Add(_stateTotalAttributes[idx]);
}
}
return colsToAdd;
}
}
XAML:
<igDP:XamDataGrid DataSource="{Binding Countries}" >
<i:Interaction.Behaviors>
<local:GridFieldLayoutBehaviour/>
</i:Interaction.Behaviors>
</igDP:XamDataGrid>
States_Data.xml:
<states>
<state name="New York" population="19,651,127" unemployment-rate="" capital="Albany" governor="Andrew Cuomo" timezone="EST" area="54,556 sq mi"></state>
<state name="New Hampshire" population="1,323,459 " unemployment-rate="" capital="Concord" governor="Maggie Hassan" timezone="EST" area="9,304 sq mi"></state>
</states>
此致,Vishwa
弄清楚了。
由於我無法粘貼代碼(從技術上講,它屬於我工作的公司),我想我只需要解決基本上解釋我做了什么。
我創建了兩個包裝器,一個用於包裝我的對象以暴露/創建層次結構(AutoGeneratedColumns =“True”,默認情況下,假設對象內部的對象集合是對象的CHILDREN),以及用於包裝新包裝器的ITypedList,所以你可以動態添加屬性。
我希望這篇文章至少可以提供一些信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.