В WPF C # Applicationm директория источника привязки списка включает «#», но приложение не может его загрузить - PullRequest
0 голосов
/ 25 июня 2019

"#" не будет работать как имя исходного каталога.

Я создаю приложение с ListBox для открытия файла XML с использованием привязки в WPF.Но я обнаружил, что даже если можно открыть в коде как XElement, невозможно привязать к источнику ListBox, потому что мое местоположение источника содержит "#" в нем.

ex) Source = 'file: /// D: / Users / имя пользователя / Documents / Visual Studio 2017 / Проекты / C # \ Windows Presentation Foundation \ ListViewBinding \ ListViewBinding \ bin \ Debug \ Teams.xml' WebException: «System.Net.WebException:« D: \ Users \ имя пользователя \ Documents \ Visual Studio 2017 \ Projects \ C »не может найти файл.

Я попытался удалить # и изменил его с« C # »на«Csharp», то это работает.Так что "#" определенно был создателем проблем.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ListViewBinding" xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="ListViewBinding.MainWindow" mc:Ignorable="d" WindowStyle="None" WindowStartupLocation="CenterScreen" Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <DataTemplate x:Key="teamItemTemplate">
        <Label Content="{Binding XPath=Name}" />
    </DataTemplate>
</Window.Resources>
 <Grid>
    <!--ListBox-->
    <Grid.DataContext>
        <XmlDataProvider x:Name="TeamData" Source="Teams.xml" XPath="Teams/Team" />
    </Grid.DataContext>

   <ListBox x:Name="TeamsListBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="155" Height="79" Margin="26,166,0,0" DockPanel.Dock="Left" ItemsSource="{Binding Source=TeamData}"  ItemTemplate="{StaticResource teamItemTemplate}" IsSynchronizedWithCurrentItem="True" >

  </ListBox>
 </Grid>
</Window>

И Teams.xml выглядит следующим образом - Этот пример только для целей тестирования.

<?xml version="1.0" encoding="utf-8" ?>
<Teams xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Team>
    <Id>1</Id>
    <Name>Arizona Cardinals</Name>
    <Conference>NFC West</Conference>
  </Team>
  <Team>
    <Id>2</Id>
    <Name>Atlanta Falcons</Name>
    <Conference>NFC South</Conference>
  </Team>
  <Team>
    <Id>3</Id>
    <Name>Baltimore Ravens</Name>
    <Conference>AFC North</Conference>
  </Team>
  <Team>
    <Id>4</Id>
    <Name>Buffalo Bills</Name>
    <Conference>AFC East</Conference>
  </Team>
  <Team>
    <Id>5</Id>
    <Name>Carolina Panthers</Name>
    <Conference>NFC South</Conference>
  </Team>
  <Team>
    <Id>6</Id>
    <Name>Chicago Bears</Name>
    <Conference>NFC North</Conference>
  </Team>
  <Team>
    <Id>7</Id>
    <Name>Cincinnati Bengals</Name>
    <Conference>AFC North</Conference>
  </Team>
  <Team>
    <Id>8</Id>
    <Name>Cleveland Browns</Name>
    <Conference>AFC North</Conference>
  </Team>
  <Team>
    <Id>9</Id>
    <Name>Dallas Cowboys</Name>
    <Conference>NFC East</Conference>
  </Team>
  <Team>
    <Id>10</Id>
    <Name>Denver Broncos</Name>
    <Conference>AFC West</Conference>
  </Team>
  <Team>
    <Id>11</Id>
    <Name>Detroit Lions</Name>
    <Conference>NFC North</Conference>
  </Team>
  <Team>
    <Id>12</Id>
    <Name>Green Bay Packers</Name>
    <Conference>NFC North</Conference>
  </Team>
  <Team>
    <Id>13</Id>
    <Name>Houston Texans</Name>
    <Conference>AFC South</Conference>
  </Team>
  <Team>
    <Id>14</Id>
    <Name>Indianapolis Colts</Name>
    <Conference>AFC South</Conference>
  </Team>
  <Team>
    <Id>15</Id>
    <Name>Jacksonville Jaguars</Name>
    <Conference>AFC South</Conference>
  </Team>
  <Team>
    <Id>16</Id>
    <Name>Kansas City Chiefs</Name>
    <Conference>AFC West</Conference>
  </Team>
  <Team>
    <Id>17</Id>
    <Name>Miami Dolphins</Name>
    <Conference>AFC East</Conference>
  </Team>
  <Team>
    <Id>18</Id>
    <Name>Minnesota Vikings</Name>
    <Conference>NFC North</Conference>
  </Team>
  <Team>
    <Id>19</Id>
    <Name>New England Patriots</Name>
    <Conference>AFC East</Conference>
  </Team>
  <Team>
    <Id>20</Id>
    <Name>New Orleans Saints</Name>
    <Conference>NFC South</Conference>
  </Team>
  <Team>
    <Id>21</Id>
    <Name>New York Giants</Name>
    <Conference>NFC East</Conference>
  </Team>
  <Team>
    <Id>22</Id>
    <Name>New York Jets</Name>
    <Conference>AFC East</Conference>
  </Team>
  <Team>
    <Id>23</Id>
    <Name>Oakland Raiders</Name>
    <Conference>AFC West</Conference>
  </Team>
  <Team>
    <Id>24</Id>
    <Name>Philadelphia Eagles</Name>
    <Conference>NFC East</Conference>
  </Team>
  <Team>
    <Id>25</Id>
    <Name>Pittsburgh Steelers</Name>
    <Conference>AFC North</Conference>
  </Team>
  <Team>
    <Id>26</Id>
    <Name>San Diego Chargers</Name>
    <Conference>AFC West</Conference>
  </Team>
  <Team>
    <Id>27</Id>
    <Name>San Francisco 49ers</Name>
    <Conference>NFC West</Conference>
  </Team>
  <Team>
    <Id>28</Id>
    <Name>St. Louis Rams</Name>
    <Conference>NFC West</Conference>
  </Team>
  <Team>
    <Id>29</Id>
    <Name>Seattle Seahawks</Name>
    <Conference>NFC West</Conference>
  </Team>
  <Team>
    <Id>30</Id>
    <Name>Tampa Bay Buccaneers</Name>
    <Conference>NFC South</Conference>
  </Team>
  <Team>
    <Id>31</Id>
    <Name>Tennessee Titans</Name>
    <Conference>AFC South</Conference>
  </Team>
  <Team>
    <Id>32</Id>
    <Name>Washington Redskins</Name>
    <Conference>NFC East</Conference>
  </Team>
</Teams>

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

public MainWindow()
    {
        InitializeComponent();


        string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
        Uri uri = new Uri(appPath + @"\Teams.xml");
        Console.WriteLine(@"Current URI Directory : " + uri);
        TeamData.Source = uri;

        Console.WriteLine(@"Current Directory: " + Directory.GetCurrentDirectory());
        Console.WriteLine(@"source = " + TeamData.Source);

        }

Я предполагаю использовать источник XML, расположенный в папках "C #", таких как "D: \ Users ... \ c # ... \ Teams.xml".

1 Ответ

1 голос
/ 25 июня 2019

Основная проблема заключается в том, что вы пытаетесь создать URI, используя неправильный синтаксис.Включив схему file:/// в текст URI, вы обещаете классу System.Uri, что вы собираетесь предоставить действительный URI, хотя на самом деле у вас его нет.

Существует много различных способовобойти это.

Самое простое - использовать %23 вместо # там, где требуется хеш-символ (знак числа).Это правильное экранирование для символов, которые в противном случае недопустимы для URI, например, #.

Например:

<XmlDataProvider x:Name="TeamData" Source="file:///D:/Users/username/Documents/Visual Studio 2017/Projects/C%23\Windows Presentation Foundation/ListViewBinding/ListViewBinding/bin/Debug/Teams.xml" XPath="Teams/Team" />

По иронии судьбы, один из других способов - это простоне включать в путь компонент file:/// и указывать обычный путь Windows.Хотя это и не рекомендуется, класс .NET System.Uri поддерживает автоматическую интерпретацию путей к файлам Windows для строк, переданных без схемы.

Например:

<XmlDataProvider x:Name="TeamData" Source="D:\Users\username\Documents\Visual Studio 2017\Projects\C#\Windows Presentation Foundation\ListViewBinding\ListViewBinding\bin\Debug\Teams.xml" XPath="Teams/Team" />

Это сработало бы просто отлично.

Все это говорит о том, что мои предпочтительные альтернативы очень мало похожи на те, что указаны выше.Первым было бы внедрить XML как ресурс в программу и просто загрузить его из URI ресурса.Будет работать простая строка, или вы можете использовать схему pack:.

Тогда вам вообще не придется иметь дело с файловой системой.

Если вы действительно хотите внешний файлдругая альтернатива - создать объект модели представления, который сделает всю работу за вас.Укажите настраиваемые свойства для пути к файлу XML и XPath для XML, а затем в модели представления при любом изменении этих свойств установите другое свойство, которое возвращает объект XmlDataProvider, в котором свойства Source и XPath имеютбыл установлен на существующие свойства модели представления.Затем вы можете просто привязать свойство ListBox.ItemsSource непосредственно к свойству XmlDataProvider модели представления (т. Е. Как ItemsSource={Binding XmlDataProvider.Data}, где предполагается, что имя свойства в модели представления равно XmlDataProvider - обратите внимание, что путь привязки должен включать Data свойство объекта XmlDataProvider, так как это фактические привязываемые данные).

Одна из приятных особенностей этого подхода заключается в том, что он упрощает работу с относительными путями, поскольку обычно XmlDataProvider пытаетсяобрабатывать вещи, которые выглядят как относительные пути, как если бы они были именами ресурсов.Это также дает вам больший контроль над процессом связывания, в случае, если вы хотите выполнить дополнительную настройку (например, включить дополнительные пути поиска для относительных путей и тому подобное).

Конечно, недостатком является то, что естьбольше кодаНо большинство из них - шаблонные, а остальные менее вероятно станут проблемой обслуживания, какой могут быть необработанные пути к файлам в XAML.

...