Поделиться через


Управление проектами универсальной версии Windows

Универсальные приложения Windows — это приложения, предназначенные для Windows 8.1 и Windows Телефон 8.1, что позволяет разработчикам использовать код и другие ресурсы на обеих платформах. Общий код и ресурсы хранятся в общем проекте, а код и ресурсы для конкретной платформы хранятся в отдельных проектах, один для Windows и другой для Windows Телефон. Дополнительные сведения о универсальных приложениях Windows см. в статье "Универсальные приложения Windows". Расширения Visual Studio, управляющие проектами, должны учитывать, что проекты универсальных приложений Windows имеют структуру, которая отличается от одноплатформенных приложений. В этом пошаговом руководстве показано, как перемещаться по общему проекту и управлять общими элементами.

  1. Создайте проект VSIX C# с именем TestUniversalProject. (Файл>нового>проекта, а затем пакет Visual Studio для C#>Extensibility).> Добавьте шаблон элемента пользовательского командного проекта (в Обозреватель решений щелкните правой кнопкой мыши узел проекта и выберите "Добавить>новый элемент", а затем перейдите к расширяемости). Назовите файл TestUniversalProject.

  2. Добавьте ссылку на Microsoft.VisualStudio.Shell.Interop.12.1.DesignTime.dll и Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.dllразделе "Расширения").

  3. Откройте TestUniversalProject.cs и добавьте следующие using директивы:

    using EnvDTE;
    using EnvDTE80;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.PlatformUI;
    using Microsoft.Internal.VisualStudio.PlatformUI;
    using System.Collections.Generic;
    using System.IO;
    using System.Windows.Forms;
    
  4. В классе добавьте частное TestUniversalProject поле, указывающее на окно вывода .

    public sealed class TestUniversalProject
    {
        IVsOutputWindowPane output;
    . . .
    }
    
  5. Задайте ссылку на область вывода в конструкторе TestUniversalProject:

    private TestUniversalProject(Package package)
    {
        if (package == null)
        {
            throw new ArgumentNullException("package");
        }
    
        this.package = package;
    
        OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
        if (commandService != null)
        {
            CommandID menuCommandID = new CommandID(MenuGroup, CommandId);
            EventHandler eventHandler = this.ShowMessageBox;
            MenuCommand menuItem = new MenuCommand(eventHandler, menuCommandID);
            commandService.AddCommand(menuItem);
        }
    
        // get a reference to the Output window
        output = (IVsOutputWindowPane)ServiceProvider.GetService(typeof(SVsGeneralOutputWindowPane));
    }
    
  6. Удалите существующий ShowMessageBox код из метода:

    private void ShowMessageBox(object sender, EventArgs e)
    {
    }
    
  7. Получите объект DTE, который мы будем использовать для нескольких различных целей в этом пошаговом руководстве. Кроме того, убедитесь, что решение загружается при нажатии кнопки меню.

    private void ShowMessageBox(object sender, EventArgs e)
    {
        var dte = (EnvDTE.DTE)this.ServiceProvider.GetService(typeof(EnvDTE.DTE));
        if (dte.Solution != null)
        {
            . . .
        }
        else
        {
            MessageBox.Show("No solution is open");
            return;
        }
    }
    
  8. Найдите общий проект. Общий проект — это чистый контейнер; Он не создает и не создает выходные данные. Следующий метод находит первый общий проект в решении, ищет IVsHierarchy объект, имеющий общую возможность проекта.

    private IVsHierarchy FindSharedProject()
    {
        var sln = (IVsSolution)this.ServiceProvider.GetService(typeof(SVsSolution));
        Guid empty = Guid.Empty;
        IEnumHierarchies enumHiers;
    
        //get all the projects in the solution
        ErrorHandler.ThrowOnFailure(sln.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref empty, out enumHiers));
        foreach (IVsHierarchy hier in ComUtilities.EnumerableFrom(enumHiers))
        {
            if (PackageUtilities.IsCapabilityMatch(hier, "SharedAssetsProject"))
            {
                return hier;
            }
        }
        return null;
    }
    
  9. В методе ShowMessageBox выводится подпись (имя проекта, которое отображается в Обозреватель решений) общего проекта.

    private void ShowMessageBox(object sender, EventArgs e)
    {
        var dte = (DTE)this.ServiceProvider.GetService(typeof(DTE));
    
        if (dte.Solution != null)
        {
            var sharedHier = this.FindSharedProject();
            if (sharedHier != null)
            {
                string sharedCaption = HierarchyUtilities.GetHierarchyProperty<string>(sharedHier, (uint)VSConstants.VSITEMID.Root,
                     (int)__VSHPROPID.VSHPROPID_Caption);
                output.OutputStringThreadSafe(string.Format("Found shared project: {0}\n", sharedCaption));
            }
            else
            {
                MessageBox.Show("Solution has no shared project");
                return;
            }
        }
        else
        {
            MessageBox.Show("No solution is open");
            return;
        }
    }
    
  10. Получите активный проект платформы. Проекты платформы — это проекты, содержащие код и ресурсы для конкретной платформы. Следующий метод использует новое поле VSHPROPID_SharedItemContextHierarchy для получения активного проекта платформы.

    private IVsHierarchy GetActiveProjectContext(IVsHierarchy hierarchy)
    {
        IVsHierarchy activeProjectContext;
        if (HierarchyUtilities.TryGetHierarchyProperty(hierarchy, (uint)VSConstants.VSITEMID.Root,
             (int)__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy, out activeProjectContext))
        {
            return activeProjectContext;
        }
        else
        {
            return null;
        }
    }
    
  11. В методе ShowMessageBox выводит подпись активного проекта платформы.

    private void ShowMessageBox(object sender, EventArgs e)
    {
        var dte = (DTE)this.ServiceProvider.GetService(typeof(DTE));
    
        if (dte.Solution != null)
        {
            var sharedHier = this.FindSharedProject();
            if (sharedHier != null)
            {
                string sharedCaption = HierarchyUtilities.GetHierarchyProperty<string>(sharedHier, (uint)VSConstants.VSITEMID.Root,
                     (int)__VSHPROPID.VSHPROPID_Caption);
                output.OutputStringThreadSafe(string.Format("Shared project: {0}\n", sharedCaption));
    
                var activePlatformHier = this.GetActiveProjectContext(sharedHier);
                if (activePlatformHier != null)
                {
                    string activeCaption = HierarchyUtilities.GetHierarchyProperty<string>(activePlatformHier,
                         (uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_Caption);
                    output.OutputStringThreadSafe(string.Format("Active platform project: {0}\n", activeCaption));
                }
                else
                {
                    MessageBox.Show("Shared project has no active platform project");
                }
            }
            else
            {
                MessageBox.Show("Solution has no shared project");
            }
        }
        else
        {
            MessageBox.Show("No solution is open");
        }
    }
    
  12. Выполните итерацию по проектам платформы. Следующий метод получает все импортируемые (платформы) проекты из общего проекта.

    private IEnumerable<IVsHierarchy> EnumImportingProjects(IVsHierarchy hierarchy)
    {
        IVsSharedAssetsProject sharedAssetsProject;
        if (HierarchyUtilities.TryGetHierarchyProperty(hierarchy, (uint)VSConstants.VSITEMID.Root,
            (int)__VSHPROPID7.VSHPROPID_SharedAssetsProject, out sharedAssetsProject)
            && sharedAssetsProject != null)
        {
            foreach (IVsHierarchy importingProject in sharedAssetsProject.EnumImportingProjects())
            {
                yield return importingProject;
            }
        }
    }
    

    Важно!

    Если пользователь открыл проект универсального приложения Windows C++ в экспериментальном экземпляре, приведенный выше код вызывает исключение. Это известная проблема. Чтобы избежать исключения, замените приведенный foreach выше блок следующим:

    var importingProjects = sharedAssetsProject.EnumImportingProjects();
    for (int i = 0; i < importingProjects.Count; ++i)
    {
        yield return importingProjects[i];
    }
    
  13. В методе ShowMessageBox выводится подпись каждого проекта платформы. Вставьте следующий код после строки, которая выводит подпись активного проекта платформы. В этом списке отображаются только загруженные проекты платформы.

    output.OutputStringThreadSafe("Platform projects:\n");
    
    IEnumerable<IVsHierarchy> projects = this.EnumImportingProjects(sharedHier);
    
    bool isActiveProjectSet = false;
    foreach (IVsHierarchy platformHier in projects)
    {
        string platformCaption = HierarchyUtilities.GetHierarchyProperty<string>(platformHier, (uint)VSConstants.VSITEMID.Root,
            (int)__VSHPROPID.VSHPROPID_Caption);
        output.OutputStringThreadSafe(string.Format(" * {0}\n", platformCaption));
    }
    
  14. Изменение активного проекта платформы. Следующий метод задает активный проект с помощью SetProperty.

    private int SetActiveProjectContext(IVsHierarchy hierarchy, IVsHierarchy activeProjectContext)
    {
        return hierarchy.SetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy, activeProjectContext);
    }
    
  15. В методе измените ShowMessageBox активный проект платформы. Вставьте этот код в foreach блок.

    bool isActiveProjectSet = false;
    string platformCaption = null;
    foreach (IVsHierarchy platformHier in projects)
    {
        platformCaption = HierarchyUtilities.GetHierarchyProperty<string>(platformHier, (uint)VSConstants.VSITEMID.Root,
             (int)__VSHPROPID.VSHPROPID_Caption);
        output.OutputStringThreadSafe(string.Format(" * {0}\n", platformCaption));
    
        // if this project is neither the shared project nor the current active platform project,
        // set it to be the active project
        if (!isActiveProjectSet && platformHier != activePlatformHier)
        {
            this.SetActiveProjectContext(sharedHier, platformHier);
            activePlatformHier = platformHier;
            isActiveProjectSet = true;
        }
    }
    output.OutputStringThreadSafe("set active project: " + platformCaption +'\n');
    
  16. Теперь попробуйте его. Нажмите клавишу F5, чтобы запустить экспериментальный экземпляр. Создайте проект универсального концентратора C# в экспериментальном экземпляре (в диалоговом окне "Новый проект", Visual C#>Windows>8>универсального концентратора>приложений). После загрузки решения перейдите в меню "Сервис" и нажмите кнопку "Вызвать TestUniversalProject", а затем проверка текст в области вывода. Вы должны увидеть нечто вроде этого:

    Found shared project: HubApp.Shared
    The active platform project: HubApp.Windows
    Platform projects:
     * HubApp.Windows
     * HubApp.WindowsPhone
    set active project: HubApp.WindowsPhone
    

Управление общими элементами в проекте платформы

  1. Найдите общие элементы в проекте платформы. Элементы в общем проекте отображаются в проекте платформы в качестве общих элементов. Их нельзя увидеть в Обозреватель решений, но их можно найти в иерархии проектов. Следующий метод проходит по иерархии и собирает все общие элементы. При необходимости он выводит подпись каждого элемента. Общие элементы определяются новым свойством VSHPROPID_IsSharedItem.

    private void InspectHierarchyItems(IVsHierarchy hier, uint itemid, int level, List<uint> itemIds, bool getSharedItems, bool printItems)
    {
        string caption = HierarchyUtilities.GetHierarchyProperty<string>(hier, itemid, (int)__VSHPROPID.VSHPROPID_Caption);
        if (printItems)
            output.OutputStringThreadSafe(string.Format("{0}{1}\n", new string('\t', level), caption));
    
        // if getSharedItems is true, inspect only shared items; if it's false, inspect only unshared items
        bool isSharedItem;
        if (HierarchyUtilities.TryGetHierarchyProperty(hier, itemid, (int)__VSHPROPID7.VSHPROPID_IsSharedItem, out isSharedItem)
            && (isSharedItem == getSharedItems))
        {
            itemIds.Add(itemid);
        }
    
        uint child;
        if (HierarchyUtilities.TryGetHierarchyProperty(hier, itemid, (int)__VSHPROPID.VSHPROPID_FirstChild, Unbox.AsUInt32, out child)
            && child != (uint)VSConstants.VSITEMID.Nil)
        {
            this.InspectHierarchyItems(hier, child, level + 1, itemIds, isSharedItem, printItems);
    
            while (HierarchyUtilities.TryGetHierarchyProperty(hier, child, (int)__VSHPROPID.VSHPROPID_NextSibling, Unbox.AsUInt32, out child)
                && child != (uint)VSConstants.VSITEMID.Nil)
            {
                this.InspectHierarchyItems(hier, child, level + 1, itemIds, isSharedItem, printItems);
            }
        }
    }
    
  2. В методе ShowMessageBox добавьте следующий код, чтобы пройти элементы иерархии проектов платформы. Вставьте его внутри foreach блока.

    output.OutputStringThreadSafe("Walk the active platform project:\n");
    var sharedItemIds = new List<uint>();
    this.InspectHierarchyItems(activePlatformHier, (uint)VSConstants.VSITEMID.Root, 1, sharedItemIds, true, true);
    
  3. Чтение общих элементов. Общие элементы отображаются в проекте платформы как скрытые связанные файлы, и вы можете читать все свойства как обычные связанные файлы. Следующий код считывает полный путь первого общего элемента.

    var sharedItemId = sharedItemIds[0];
    string fullPath;
    ErrorHandler.ThrowOnFailure(((IVsProject)activePlatformHier).GetMkDocument(sharedItemId, out fullPath));
    output.OutputStringThreadSafe(string.Format("Shared item full path: {0}\n", fullPath));
    
  4. Теперь попробуйте его. Нажмите клавишу F5 , чтобы запустить экспериментальный экземпляр. Создайте проект универсального концентратора C# в экспериментальном экземпляре (в диалоговом окне "Новый проект" Visual C#>Windows Windows>8>Универсальное>концентраторное приложение) перейдите в меню "Сервис" и нажмите кнопку "Вызвать TestUniversalProject", а затем проверка текст на панели вывода. Вы должны увидеть нечто вроде этого:

    Found shared project: HubApp.Shared
    The active platform project: HubApp.Windows
    Platform projects:
     * HubApp.Windows
     * HubApp.WindowsPhone
    set active project: HubApp.WindowsPhone
    Walk the active platform project:
        HubApp.WindowsPhone
            <HubApp.Shared>
                App.xaml
                    App.xaml.cs
                Assets
                    DarkGray.png
                    LightGray.png
                    MediumGray.png
                Common
                    NavigationHelper.cs
                    ObservableDictionary.cs
                    RelayCommand.cs
                    SuspensionManager.cs
                DataModel
                    SampleData.json
                    SampleDataSource.cs
                HubApp.Shared.projitems
                Strings
                    en-US
                        Resources.resw
            Assets
                HubBackground.theme-dark.png
                HubBackground.theme-light.png
                Logo.scale-240.png
                SmallLogo.scale-240.png
                SplashScreen.scale-240.png
                Square71x71Logo.scale-240.png
                StoreLogo.scale-240.png
                WideLogo.scale-240.png
            HubPage.xaml
                HubPage.xaml.cs
            ItemPage.xaml
                ItemPage.xaml.cs
            Package.appxmanifest
            Properties
                AssemblyInfo.cs
            References
                .NET for Windows Store apps
                HubApp.Shared
                Windows Phone 8.1
            SectionPage.xaml
                SectionPage.xaml.cs
    

Обнаружение изменений в проектах платформы и общих проектов

  1. Вы можете использовать события иерархии и проекта для обнаружения изменений в общих проектах, как и для проектов платформы. Однако элементы проекта в общем проекте не видны, что означает, что некоторые события не запускаются при изменении общих элементов проекта.

    Рассмотрим последовательность событий при переименовании файла в проекте:

    1. Имя файла изменяется на диске.

    2. Файл проекта обновляется, чтобы включить новое имя файла.

      События иерархии (например, ) обычно отслеживают изменения, отображаемые в пользовательском интерфейсе, IVsHierarchyEventsкак в Обозреватель решений. События иерархии считают операцию переименования файла, состоящую из удаления файла, а затем добавления файла. Однако при изменении невидимых элементов система событий иерархии запускает OnItemDeleted событие, но не OnItemAdded событие. Таким образом, если вы переименовываете файл в проекте платформы, вы получите оба OnItemDeleted и OnItemAdded, но при переименовании файла в общем проекте вы получите только OnItemDeleted.

      Чтобы отслеживать изменения в элементах проекта, можно обрабатывать события элементов проекта DTE (найденные в ProjectItemsEventsClass). Однако при обработке большого количества событий можно повысить производительность в IVsTrackProjectDocuments2событиях. В этом пошаговом руководстве показаны только события иерархии и события DTE. В этой процедуре вы добавите прослушиватель событий в общий проект и проект платформы. Затем при переименовании одного файла в общем проекте и другом файле в проекте платформы можно увидеть события, которые запускаются для каждой операции переименования.

      В этой процедуре вы добавите прослушиватель событий в общий проект и проект платформы. Затем при переименовании одного файла в общем проекте и другом файле в проекте платформы можно увидеть события, которые запускаются для каждой операции переименования.

  2. Добавьте прослушиватель событий. Добавьте новый файл класса в проект и вызовите его HierarchyEventListener.cs.

  3. Откройте файл HierarchyEventListener.cs и добавьте следующие директивы using:

    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio;
    using System.IO;
    
  4. Реализуйте HierarchyEventListener класс IVsHierarchyEvents:

    class HierarchyEventListener : IVsHierarchyEvents
    { }
    
  5. Реализуйте элементы IVsHierarchyEvents, как в приведенном ниже коде.

    class HierarchyEventListener : IVsHierarchyEvents
    {
        private IVsHierarchy hierarchy;
        IVsOutputWindowPane output;
    
        internal HierarchyEventListener(IVsHierarchy hierarchy, IVsOutputWindowPane outputWindow) {
             this.hierarchy = hierarchy;
             this.output = outputWindow;
        }
    
        int IVsHierarchyEvents.OnInvalidateIcon(IntPtr hIcon) {
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnInvalidateItems(uint itemIDParent) {
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnItemAdded(uint itemIDParent, uint itemIDSiblingPrev, uint itemIDAdded) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnItemAdded: " + itemIDAdded + "\n");
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnItemDeleted(uint itemID) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnItemDeleted: " + itemID + "\n");
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnItemsAppended(uint itemIDParent) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnItemsAppended\n");
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnPropertyChanged(uint itemID, int propID, uint flags) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnPropertyChanged: item ID " + itemID + "\n");
            return VSConstants.S_OK;
        }
    }
    
  6. В том же классе добавьте другой обработчик событий для события ItemRenamedDTE, который возникает при переименовании элемента проекта.

    public void OnItemRenamed(EnvDTE.ProjectItem projItem, string oldName)
    {
        output.OutputStringThreadSafe(string.Format("[Event] Renamed {0} to {1} in project {2}\n",
             oldName, Path.GetFileName(projItem.get_FileNames(1)), projItem.ContainingProject.Name));
    }
    
  7. Зарегистрируйтесь для событий иерархии. Необходимо зарегистрироваться отдельно для каждого проекта, который вы отслеживаете. Добавьте следующий код в ShowMessageBox, один для общего проекта и другой для одного из проектов платформы.

    // hook up the event listener for hierarchy events on the shared project
    HierarchyEventListener listener1 = new HierarchyEventListener(sharedHier, output);
    uint cookie1;
    sharedHier.AdviseHierarchyEvents(listener1, out cookie1);
    
    // hook up the event listener for hierarchy events on the
    active project
    HierarchyEventListener listener2 = new HierarchyEventListener(activePlatformHier, output);
    uint cookie2;
    activePlatformHier.AdviseHierarchyEvents(listener2, out cookie2);
    
  8. Зарегистрируйтесь для события ItemRenamedэлемента проекта DTE. Добавьте следующий код после подключения второго прослушивателя.

    // hook up DTE events for project items
    Events2 dteEvents = (Events2)dte.Events;
    dteEvents.ProjectItemsEvents.ItemRenamed += listener1.OnItemRenamed;
    
  9. Измените общий элемент. Нельзя изменять общие элементы в проекте платформы; Вместо этого необходимо изменить их в общем проекте, который является фактическим владельцем этих элементов. Вы можете получить соответствующий идентификатор элемента в общем проекте IsDocumentInProject, предоставив ему полный путь к общему элементу. Затем можно изменить общий элемент. Изменение распространяется на проекты платформы.

    Важно!

    Перед изменением элемента проекта необходимо выяснить, является ли элемент проекта общим.

    Следующий метод изменяет имя файла элемента проекта.

    private void ModifyFileNameInProject(IVsHierarchy project, string path)
    {
        int found;
        uint projectItemID;
        VSDOCUMENTPRIORITY[] priority = new VSDOCUMENTPRIORITY[1];
        if (ErrorHandler.Succeeded(((IVsProject)project).IsDocumentInProject(path, out found, priority, out projectItemID))
            && found != 0)
        {
            var name = DateTime.Now.Ticks.ToString() + Path.GetExtension(path);
            project.SetProperty(projectItemID, (int)__VSHPROPID.VSHPROPID_EditLabel, name);
            output.OutputStringThreadSafe(string.Format("Renamed {0} to {1}\n", path,name));
        }
    }
    
  10. Вызовите этот метод после всего другого кода, ShowMessageBox чтобы изменить имя файла в общем проекте. Вставьте его после кода, который получает полный путь к элементу в общем проекте.

    // change the file name of an item in a shared project
    this.InspectHierarchyItems(activePlatformHier, (uint)VSConstants.VSITEMID.Root, 1, sharedItemIds, true, true);
    ErrorHandler.ThrowOnFailure(((IVsProject)activePlatformHier).GetMkDocument(sharedItemId, out fullPath));
    output.OutputStringThreadSafe(string.Format("Shared project item ID = {0}, full path = {1}\n", sharedItemId, fullPath));
    this.ModifyFileNameInProject(sharedHier, fullPath);
    
  11. Постройте и запустите проект. Создайте универсальное приложение центра C# в экспериментальном экземпляре, перейдите в меню "Сервис" и щелкните "Вызвать TestUniversalProject" и проверка текст в общей области вывода. Имя первого элемента в общем проекте (мы ожидаем, что это файл App.xaml ) должно быть изменено, и вы увидите, что ItemRenamed событие сработало. В этом случае, так как переименование App.xaml приводит к переименованию App.xaml.cs , вы должны увидеть четыре события (два для каждого проекта платформы). (События DTE не отслеживают элементы в общем проекте.) Вы должны увидеть два OnItemDeleted события (по одному для каждого проекта платформы), но никаких OnItemAdded событий.

  12. Теперь попробуйте переименовать файл в проекте платформы, и вы можете увидеть разницу в событиях, которые будут запущены. Добавьте следующий код ShowMessageBox после вызова ModifyFileName.

    // change the file name of an item in a platform project
    var unsharedItemIds = new List<uint>();
    this.InspectHierarchyItems(activePlatformHier, (uint)VSConstants.VSITEMID.Root, 1, unsharedItemIds, false, false);
    
    var unsharedItemId = unsharedItemIds[0];
    string unsharedPath;
    ErrorHandler.ThrowOnFailure(((IVsProject)activePlatformHier).GetMkDocument(unsharedItemId, out unsharedPath));
    output.OutputStringThreadSafe(string.Format("Platform project item ID = {0}, full path = {1}\n", unsharedItemId, unsharedPath));
    
    this.ModifyFileNameInProject(activePlatformHier, unsharedPath);
    
  13. Постройте и запустите проект. Создайте универсальный проект C# в экспериментальном экземпляре, перейдите в меню "Сервис" и щелкните "Вызвать TestUniversalProject" и проверка текст в общей области вывода. После переименования файла в проекте платформы вы увидите как событие, так OnItemAdded и OnItemDeleted событие. Так как изменение файла не привело к изменению других файлов, и поскольку изменения элементов в проекте платформы не распространяются нигде, существует только один из этих событий.