やっとやった!
保存/ロードするWPFリボンサンプルに基づいています。datacontextを使用してRibbonControlのコントロールをローカライズしましたが、気に入らなかったので、QuickAccessToolBarIdを使用してコントロールをローカライズしました。
これが解決策です。- OnClosingアプリケーション:
QuickAccessToolBarを保存し、QuickAccessToolBarでリボンコントロールのアイテムを検索し、パスを保存します。注:アイテムがアプリケーションメニューにある場合、最初のパスは-1.A- OnLoadApplication:
アイテムをロードし、パスによるリボンコントロールをシークします。
そしてこれはコードです:
RibbonHelper:
class RibbonHelper
{
Ribbon ribbon;
public RibbonHelper(Ribbon ribbon)
{
this.ribbon = ribbon;
}
string _qatFileName = "qat.xml";
internal void Save()
{
try
{
SaveQatItems();
}
catch { }
}
internal void Load()
{
try
{
LoadQatItems();
}
catch
{
}
}
#region Save Qat
private void SaveQatItems()
{
QatItemCollection qatItems = GetQatItemsToSave(ribbon.QuickAccessToolBar);
if (qatItems != null)
{
QatItemCollection remainingItems = new QatItemCollection();
remainingItems.AddRange(qatItems);
SaveQatItemsOfApplicationMenu(remainingItems);
SaveQatItemsOfTabs(remainingItems);
SaveQatItems(qatItems);
}
}
private void SaveQatItems(QatItemCollection qatItems)
{
XmlWriter xmlWriter = XmlWriter.Create(_qatFileName);
XamlWriter.Save(qatItems, xmlWriter);
xmlWriter.Close();
}
private void SaveQatItemsOfApplicationMenu(QatItemCollection remainingItems)
{
if (ribbon.ApplicationMenu != null)
{
if (remainingItems != null)
{
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Add(-1);
});
for (int index = 0; index < ribbon.ApplicationMenu.Items.Count && remainingItems.Count > 0; index++)
{
SaveQatItemsAmongChildren(remainingItems, ribbon.ApplicationMenu.Items[index],index);
}
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Clear();
});
}
}
}
private void SaveQatItemsOfTabs(QatItemCollection remainingItems)
{
if (ribbon.Items != null)
{
if (remainingItems != null)
{
for (int tabIndex = 0; tabIndex < ribbon.Items.Count && remainingItems.Count > 0; tabIndex++)
{
RibbonTab tab = ribbon.Items[tabIndex] as RibbonTab;
SaveQatItemsAmongChildren(remainingItems, tab, tabIndex);
}
}
}
}
private void SaveQatItemsAmongChildren(QatItemCollection remainingItems, object control, int controlIndex)
{
if (control == null)
{
return;
}
//Añaidmos el control index a los pendientes
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Add(controlIndex);
});
SaveQatItemsAmongChildrenInner(remainingItems, control);
//Eliminamos el control index de los pendientes ya que no estan dentro de ese control
remainingItems.ForEach(qat =>
{
int last = qat.ControlIndices.Count - 1;
qat.ControlIndices.RemoveAt(last);
});
}
private void SaveQatItemsAmongChildrenInner(QatItemCollection remainingItems, object parent)
{
SaveQatItemsIfMatchesControl(remainingItems, parent);
if (remainingItems.Count == 0 || IsLeaf(parent))
{
return;
}
int childIndex = 0;
DependencyObject dependencyObject = parent as DependencyObject;
if (dependencyObject != null)
{
IEnumerable children = LogicalTreeHelper.GetChildren(dependencyObject);
foreach (object child in children)
{
SaveQatItemsAmongChildren(remainingItems, child, childIndex);
childIndex++;
}
}
if (childIndex != 0)
{
return;
}
// if we failed to get any logical children, enumerate the visual ones
Visual visual = parent as Visual;
if (visual == null)
{
return;
}
for (childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(visual); childIndex++)
{
Visual child = VisualTreeHelper.GetChild(visual, childIndex) as Visual;
SaveQatItemsAmongChildren(remainingItems, child, childIndex);
}
}
private bool IsLeaf(object element)
{
if ((element is RibbonButton) ||
(element is RibbonToggleButton) ||
(element is RibbonRadioButton) ||
(element is RibbonCheckBox) ||
(element is RibbonTextBox) ||
(element is RibbonSeparator))
{
return true;
}
RibbonMenuItem menuItem = element as RibbonMenuItem;
if (menuItem != null &&
menuItem.Items.Count == 0)
{
return true;
}
return false;
}
private bool SaveQatItemsIfMatchesControl(QatItemCollection remainingItems, object control)
{
bool matched = false;
FrameworkElement element = control as FrameworkElement;
if (element != null)
{
object getQuickAccessToolBarId = RibbonControlService.GetQuickAccessToolBarId(element);
if (getQuickAccessToolBarId != null)
{
int remove = remainingItems.RemoveAll(qat => qat.QuickAccessToolBarIdHashCode == getQuickAccessToolBarId.GetHashCode());
matched = remove > 0;
}
}
return matched;
}
private QatItemCollection GetQatItemsToSave(RibbonQuickAccessToolBar qat)
{
QatItemCollection qatItems = new QatItemCollection();
if (qat != null && qat.Items != null && qat.Items.Count > 0)
{
foreach (var item in qat.Items)
{
FrameworkElement element = item as FrameworkElement;
if (element != null)
{
object getQuickAccessToolBarId = RibbonControlService.GetQuickAccessToolBarId(element);
if (getQuickAccessToolBarId != null)
{
QatItem qatItem = new QatItem(getQuickAccessToolBarId.GetHashCode());
qatItems.Add(qatItem);
}
}
}
}
return qatItems;
}
#endregion
#region load qat
private void LoadQatItems()
{
if (ribbon.QuickAccessToolBar == null)
{
ribbon.QuickAccessToolBar = new RibbonQuickAccessToolBar();
}
QatItemCollection qatItems = GetQatItemsToLoad();
if ((qatItems != null) && (qatItems.Count > 0))
{
SearchInApplicationMenu(qatItems);
SearchInTabs(qatItems);
qatItems.Where(qat => qat.Owner != null).ToList().ForEach(qat =>
{
if (RibbonCommands.AddToQuickAccessToolBarCommand.CanExecute(null, qat.Owner))
{
RibbonCommands.AddToQuickAccessToolBarCommand.Execute(null, qat.Owner);
}
});
}
}
private void SearchInApplicationMenu(QatItemCollection qatItems)
{
if (qatItems != null)
{
int remainingItemsCount = qatItems.Count(qat=>qat.Owner==null);
QatItemCollection matchedItems = new QatItemCollection();
for (int index = 0; index < ribbon.ApplicationMenu.Items.Count && remainingItemsCount > 0; index++)
{
matchedItems.Clear();
matchedItems.AddRange(qatItems.Where(qat => qat.ControlIndices[0] == -1)); //-1 is applicationMenu
//remove -1
matchedItems.ForEach(qat =>
{
qat.ControlIndices.RemoveAt(0);
}
);
object item = ribbon.ApplicationMenu.Items[index];
if (item != null)
{
if (!IsLeaf(item))
{
LoadQatItemsAmongChildren(matchedItems, 0, index, item, ref remainingItemsCount);
}
else
{
LoadQatItemIfMatchesControl(matchedItems, new QatItemCollection(), 0, index, item, ref remainingItemsCount);
}
}
//Add -1
matchedItems.ForEach(qat =>
{
qat.ControlIndices.Insert(0, -1);
});
}
}
}
private void SearchInTabs(QatItemCollection qatItems)
{
int remainingItemsCount = qatItems.Count(qat => qat.Owner == null);
QatItemCollection matchedItems = new QatItemCollection();
for (int tabIndex = 0; tabIndex < ribbon.Items.Count && remainingItemsCount > 0; tabIndex++)
{
matchedItems.Clear();
matchedItems.AddRange(qatItems.Where(qat => qat.ControlIndices[0] == tabIndex));
RibbonTab tab = ribbon.Items[tabIndex] as RibbonTab;
if (tab != null)
{
LoadQatItemsAmongChildren(matchedItems, 0, tabIndex, tab, ref remainingItemsCount);
}
}
}
private void LoadQatItemsAmongChildren(
QatItemCollection previouslyMatchedItems,
int matchLevel,
int controlIndex,
object parent,
ref int remainingItemsCount)
{
if (previouslyMatchedItems.Count == 0)
{
return;
}
if (IsLeaf(parent))
{
return;
}
int childIndex = 0;
DependencyObject dependencyObject = parent as DependencyObject;
if (dependencyObject != null)
{
IEnumerable children = LogicalTreeHelper.GetChildren(dependencyObject);
foreach (object child in children)
{
if (remainingItemsCount == 0)
{
break;
}
QatItemCollection matchedItems = new QatItemCollection();
LoadQatItemIfMatchesControl(previouslyMatchedItems, matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
LoadQatItemsAmongChildren(matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
childIndex++;
}
}
if (childIndex != 0)
{
return;
}
// if we failed to get any logical children, enumerate the visual ones
Visual visual = parent as Visual;
if (visual == null)
{
return;
}
for (childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(visual); childIndex++)
{
if (remainingItemsCount == 0)
{
break;
}
Visual child = VisualTreeHelper.GetChild(visual, childIndex) as Visual;
QatItemCollection matchedItems = new QatItemCollection();
LoadQatItemIfMatchesControl(previouslyMatchedItems, matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
LoadQatItemsAmongChildren(matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
}
}
private void LoadQatItemIfMatchesControl(
QatItemCollection previouslyMatchedItems,
QatItemCollection matchedItems,
int matchLevel,
int controlIndex,
object control,
ref int remainingItemsCount)
{
for (int qatIndex = 0; qatIndex < previouslyMatchedItems.Count; qatIndex++)
{
QatItem qatItem = previouslyMatchedItems[qatIndex];
if (qatItem.ControlIndices[matchLevel] == controlIndex)
{
if (qatItem.ControlIndices.Count == matchLevel + 1)
{
qatItem.Owner = control as Control; ;
remainingItemsCount--;
}
else
{
matchedItems.Add(qatItem);
}
}
}
}
private QatItemCollection GetQatItemsToLoad()
{
try
{
if (File.Exists(_qatFileName))
{
using (XmlReader xmlReader = XmlReader.Create(_qatFileName))
{
QatItemCollection qatItems = (QatItemCollection)XamlReader.Load(xmlReader);
xmlReader.Close();
return qatItems;
}
}
}
catch
{
//Do nothing, return null;
}
return null;
}
#endregion
}
シリアル化するクラス:
public class QatItem {
public QatItem()
{
}
public QatItem(int qatbIdHashCode)
{
QuickAccessToolBarIdHashCode = qatbIdHashCode;
}
public Int32Collection ControlIndices
{
get
{
if (_controlIndices == null)
{
_controlIndices = new Int32Collection();
}
return _controlIndices;
}
set
{
_controlIndices = value;
}
}
Int32Collection _controlIndices;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int QuickAccessToolBarIdHashCode { get; set; }
//Is only for load
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Control Owner { get; set; }
}
public class QatItemCollection : List<QatItem>
{
}
そしてこれはウィンドウから保存/ロードするコードです
RibbonHelper helper;
protected override void OnClosing(CancelEventArgs e)
{
helper.Save();
base.OnClosing(e);
}
private void RibbonWindow_Loaded(object sender, RoutedEventArgs e)
{
helper = new RibbonHelper(ribbon);
helper.Load();
}