找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1160|回复: 0

[分享] Adding a WPF document tab in AutoCAD 2015 using .NET

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-5-11 17:25:42 来自手机 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 csharp 于 2014-5-11 18:36 编辑

http://through-the-interface.typepad.com/through_the_interface/autocad_net/

A few people expressed an interest in understanding how AutoCAD 2015’s ability to open HTML pages inside its frame – shown in this recent post – could be extended to work with “native” user interfaces. This post shows how that can be done using WPF – the other supported mechanism for adding new documents to AutoCAD’s main frame introduced in the 2015 release.
Just as with last week’s post, there really isn’t that much to it: you just need to add your own WPF UserControl to the project and load that into an Autodesk.AutoCAD.Windows.WPFDocumentWindow object and pass it to other version of the DocumentCollection.AddWindowDocument() method. So I went ahead and added a little code to load some hardcoded XML data into a DataGrid hosted by said UserControl. It’s very basic – I haven’t taken care of any real-world concerns in this sample – but then it’s better than staring at a blank window. :-)
Here’s the updated C# code that adds our ADW command to the code we saw last week. You’ll notice it also adds a couple of single-line commands to tile child windows vertically and horizontally, to show how simple that is to implement.
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using System;
using System.Net;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace NewDocumentWindow
{
  // To check whether a page exists, we can use a HEAD request
  // rather than a full GET. Derive a custom client to do that

  class HeadClient : WebClient
  {
    protected override WebRequest GetWebRequest(Uri address)
    {
      var req = base.GetWebRequest(address);
      if (req.Method == "GET")
        req.Method = "HEAD";
      return req;
    }
  }

  public class Commands
  {
    // Asynchronous helper that checks whether a URL exists
    // (i.e. that the URL is valid and can be loaded)

    private async static Task<bool> PageExists(string url)
    {
      // First check whether the URL is valid

      Uri uriResult;
      if (
        !Uri.TryCreate(url, UriKind.Absolute, out uriResult) ||
        uriResult.Scheme != Uri.UriSchemeHttp
      )
        return false;

      // Then we try to peform a HEAD request on the page
      // (a WebException will be fired if it doesn't exist)

      try
      {
        using(var client = new HeadClient())
        {
          await client.DownloadStringTaskAsync(url);
        }
        return true;
      }
      catch (WebException)
      {
        return false;
      }
    }

    [CommandMethod("BLOG")]
    public async static void OpenBlog()
    {
      const string url =
        "http://blogs.autodesk.com/through-the-interface";

      // As we're calling an async function, we need to await
      // (and mark the command itself as async)

      if (await PageExists(url))
      {
        // Now that we've validated the URL, we can call the
        // new API in AutoCAD 2015 to load our page

        Application.DocumentWindowCollection.AddDocumentWindow(
          "Kean's blog", new System.Uri(url)
        );
      }
      else
      {
        // Print a helpful message if the URL wasn't loadable

        var doc = Application.DocumentManager.MdiActiveDocument;
        var ed = doc.Editor;

        ed.WriteMessage(
          "\nCould not load url: \"{0}\".", url
        );
      }
    }

    [CommandMethod("ADW")]
    public static void AddDocumentWindow()
    {
      // Hardcode some XML data

      var xdoc =
        XElement.Parse(@"
          <orders>
            <order Customer=""ACME"" Item=""Widget"" Price=""100"" />
            <order Customer=""ACME"" Item=""Tyre"" Price=""200"" />
            <order Customer=""Amazon"" Item=""Pen"" Price=""50""/>
            <order Customer=""Amazon"" Item=""Paper"" Price=""20""/>
            <order Customer=""Autodesk"" Item=""CAD"" Price=""10""/>
            <order Customer=""Autodesk"" Item=""File"" Price=""40""/>
            <order Customer=""ABC"" Item=""Flowers"" Price=""503""/>
            <order Customer=""ABC"" Item=""Sand"" Price=""706""/>
          </orders>"
        );

      // Create our WindowContent WPF UserControl and set the
      // XML data on our DataGrid object

      var wc = new WindowContent();
      wc.MyGrid.DataContext = xdoc;

      // Create a WPFDocumentWindow for our content then open it

      var dw = new WPFDocumentWindow(wc);
      dw.Title = "WPF Document Window";
      Application.DocumentWindowCollection.AddDocumentWindow(dw);
    }

    [CommandMethod("TV")]
    public static void TileVertically()
    {
      Application.DocumentWindowCollection.TileVertically();
    }

    [CommandMethod("TH")]
    public static void TileHorizontally()
    {
      Application.DocumentWindowCollection.TileHorizontally();
    }
  }
}

Here’s also the XAML definition of the WPF UserControl I added to the project. Again, very simple stuff.
<UserControl
  x:Class="NewDocumentWindow.WindowContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc=
   "http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  mc:Ignorable="d"
  d:DesignHeight="300" d:DesignWidth="300">
  <Grid>
    <DataGrid
     x:Name="MyGrid"
     AutoGenerateColumns="False"
     ItemsSource="{Binding Path=Elements[order]}"
     HorizontalContentAlignment="Stretch"
     VerticalContentAlignment="Stretch"
     FontFamily="Gisha" FontSize="24">
      <DataGrid.Columns>
        <DataGridTextColumn
         Header="Customer"
         Binding="{Binding Path=Attribute[Customer].Value}"/>
        <DataGridTextColumn
         Header="Item"
         Binding="{Binding Path=Attribute[Item].Value}"/>
        <DataGridTextColumn
         Header="Price"
         Binding="{Binding Path=Attribute[Price].Value}"/>
      </DataGrid.Columns>
    </DataGrid>
  </Grid>
</UserControl>

When we run the ADW command, we see our new window gets created inside the AutoCAD frame:
0.jpg
If we run the TH command, we see our two windows get tiled horizontally:
1.jpg
Running the previously-defined BLOG command and then tiling vertically using the TV command gives us three windows across the width of the application frame:
2.jpg
With sub-windows in tiled mode, the Windows theme does impact the overall visual impression given by AutoCAD’s dark theme, but then this is likely to be an uncommon way for people to work (and then it’s always an option for the user to adjust the Windows theme, too).
That’s it for this post. From a UI perspective there are still some capabilities I’d like to explore in AutoCAD 2015, particularly around the theming of PaletteSets. Hopefully we’ll take a look at that in the next week or so.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-1-6 00:49 , Processed in 0.416279 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表