Работа с пропорциональными размерами в WPF

Автор: Мэхеш Чанд (Mahesh Chand)

В этой статье показывается как реализовать процент таблицы в качестве возможности WPF, используя панель сетки Grid .

В HTML знак процента (%) используется, чтобы определить однородную структуру, сохраняющую то же отношение ширины и высоты при изменении размера веб-страницы. В Windows Forms эта функция отсутствует. Но WPF поддерживает эту возможность другим способом, используя суффикс-звездочку (*) с двойным числом. В отличие от процента у звездочки нет максимального ограничения, равного 100. Если указана звездочка, используется текущее значение ширины или высоты элемента, которое делится на значение, связанное со звездочкой, так что при изменении размера окна или страницы фактический размер элемента рассчитывается во время выполнения.

Рассмотрим следующий пример. На рис. 1 показано окно с панелью Grid (сетка) и тремя прямоугольниками (элементы Rectangle).

Рис. 1.

Такой интерфейс пользователя можно создать, просто поместив три прямоугольника в нужные места на элемент Grid.  XAML-код выглядит, как на в примере кода 1.

<Grid>      
    <Rectangle Name="rectangle1" Stroke="Black" Fill="Orange" Margin="55,0,112,80" />
    <Rectangle Fill="Green" Margin="0,80,0,0" Name="rectangle2" Stroke="Black"
               HorizontalAlignment="Right" Width="113" />
    <Rectangle Fill="Purple" Margin="0,80,0,0" Name="rectangle3" Stroke="Black"
               HorizontalAlignment="Left" Width="54" />
</Grid>

Теперь при изменении размеров окна нужно, чтобы отношение размеров прямоугольников соответствовало новому размеру окна. Для этого можно воспользоваться звездочкой с размером.

Но все элементы в XAML не поддерживают функцию звездочки. Разместим столбцы и строки в элементе Grid и зафиксируем их ширину и длину звездочкой.

Новый код приведен в примере кода 2.

<Window x:Class="PercentageInWPF.Window1"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="200" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="139*" />
            <RowDefinition Height="150*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="101*" />
            <ColumnDefinition Width="208*" />
            <ColumnDefinition Width="169*" />
        </Grid.ColumnDefinitions>
        <Rectangle Grid.Column="1" Name="rectangle1" Stroke="Black" Fill="Orange" />
        <Rectangle Fill="Green" Name="rectangle2" Stroke="Black" Grid.Column="2" Grid.Row="1" />
        <Rectangle Fill="Purple" Name="rectangle3" Stroke="Black" Grid.Row="1" />     
    </Grid>
</Window>

Теперь при изменении размера окна пропорционально этому изменению будет изменен и размер прямоугольников.

Рис. 2.

Дополнительные подробности можно узнать, загрузив прилагаемый исходный код.

public void CreateResourceDictionary(string targetfile, string destinationfile, DoWorkEventArgs e)
        {
 
            DateTime startTime = DateTime.Now;
            e.Result = "";
 
            XDocument document = XDocument.Load(targetfile);
            oWorker.ReportProgress(2, "Initializing...");
            foreach (XElement elem in document.Descendants("{clr-namespace:System;assembly=mscorlib}String"))
            {
                XAttribute attribute = elem.Attribute("{https://schemas.microsoft.com/winfx/2006/xaml}Key");
                elememnts.Add(attribute.Value, elem.Value);
            }
 
            oWorker.ReportProgress(4, "Target File Read Successfully.");
 
            XDocument targetDocument = null;
            XNamespace xaml = "https://schemas.microsoft.com/winfx/2006/xaml/presentation";
            XNamespace x = "https://schemas.microsoft.com/winfx/2006/xaml";
            XNamespace system = "clr-namespace:System;assembly=mscorlib";
            XElement root = new XElement(xaml + "ResourceDictionary",
                                        new XAttribute("xmlns", "https://schemas.microsoft.com/winfx/2006/xaml/presentation"),
                                        new XAttribute(XNamespace.Xmlns + "x", "https://schemas.microsoft.com/winfx/2006/xaml"),
                                        new XAttribute(XNamespace.Xmlns + "system", "clr-namespace:System;assembly=mscorlib"));
 
            oWorker.ReportProgress(5, "Creating Target File.");
            int elements = elememnts.Count;
            int i = 1;
            foreach (string key in elememnts.Keys)
            {
                try
                {
                    using (LiveSearchPortTypeClient client = new LiveSearchPortTypeClient())
                    {
                        string sCode = this.Currentsource.Code;
                        string tCode = this.CurrentTarget.Code;
                        SearchResponse response = client.Search(BuildRequest(elememnts[key], sCode, tCode));
                        if (response.Translation.Results.Count() > 0)
                        {
                            string item = response.Translation.Results[0].TranslatedTerm;
                            XElement element = new XElement(system + "String", item);
                            element.Add(new XAttribute(x + "Key", key));
                            root.Add(element);
                            int percentage = ((i * 90)/elements) + 5;
                            oWorker.ReportProgress(percentage, string.Format("string {0} is converted as {1}", elememnts[key], item));
 
                            //Cancel the WORKER
                            if (oWorker.CancellationPending)
                            {
                                e.Cancel = true;
                                break;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    // Исключение при доступе к сети.
                    oWorker.ReportProgress(((i * 90) / elements) + 5, ex.Message);
                }
                i = i+1;
 
            }
            targetDocument = targetDocument ?? new XDocument();
            targetDocument.Add(root);
            targetDocument.Save(destinationfile);
            oWorker.ReportProgress(100, "Target file created Successfully");
            TimeSpan span = DateTime.Now - startTime;
            e.Result = string.Concat(span.TotalSeconds, " seconds");
            
        }
 
        public static SearchRequest BuildRequest(string query, string sCode, string tCode)
        {
            SearchRequest request = new SearchRequest();
 
            request.AppId = "3382CF24D27D0A095C7C4945EA17FDD8E2946C73";
            request.Query = query;
            request.Sources = new SourceType[] { SourceType.Translation };
 
            request.Translation = new TranslationRequest();
            
            request.Translation.SourceLanguage = sCode;
            request.Translation.TargetLanguage = tCode;
 
            request.Version = "2.2";
 
            return request;
        }

Можно видеть, что вызов BuildRequest фактически создает объект SearchRequest, используемый для вызова переводчика Bing. Переменные SourceLanguage и TargetLanguage позволят задать значения языка и региональных параметров.

Затем с помощью объекта LiveSearchPortTypeClient будет вызван запрос поиска. Вызов client.Search(Request) получает объект запроса и возвращает результат. Возможные результаты можно найти в коллекции response.Translation.Results.

Можно видеть, что созданная логика использует объекты XDocument для создания того же результата, который нам нужен для ресурса.

Я надеюсь, что это решение окажется полезным.