Skip to content

Instantly share code, notes, and snippets.

@ImaginaryDevelopment
Created October 16, 2018 16:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ImaginaryDevelopment/0377960c53f679626167ad8f309fa7ed to your computer and use it in GitHub Desktop.
Save ImaginaryDevelopment/0377960c53f679626167ad8f309fa7ed to your computer and use it in GitHub Desktop.
Demonstrate making a Wpf Frame control's Arrows enlarging
using System.Windows;
using System.Windows.Controls;
void Main()
{
var w = new Window();
var grid = new Grid();
// Func<FrameworkElement,UIElement> getTemplateChild = x => {
// var flags = BindingFlags.NonPublic | BindingFlags.Instance
// var tcm = x.GetType().GetMember("get_TemplateChild", flags)[0] as MethodInfo;
// var result = tcm.Invoke(x,null);
// return result as UIElement;
// };
grid.RowDefinitions.Add(new RowDefinition(){MinHeight=80,Height=new GridLength(80)});
grid.RowDefinitions.Add(new RowDefinition(){Height=new GridLength(200)});
grid.RowDefinitions.Add(new RowDefinition(){Height=new GridLength(200)});
grid.Children.Add(GenerateDemoFrame(1));
var frame2 = GenerateDemoFrame(2);
grid.Children.Add(frame2);
w.Content = grid;
w.Dump();
FixArrowSize(frame2);
}
static Frame GenerateDemoFrame(int gridRow) {
var f = new Frame();
f.NavigationUIVisibility = System.Windows.Navigation.NavigationUIVisibility.Visible;
var page = new Page() { Content = new Button() { Content = $"Hello from row {gridRow + 1} (index {gridRow})"}};
f.Navigate(page);
f.SetValue(Grid.RowProperty,gridRow);
return f;
}
static UIElement GetTemplateChild(FrameworkElement x)
{
var flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
var tcm = x.GetType().GetMember("get_TemplateChild", flags)[0] as System.Reflection.MethodInfo;
var result = tcm.Invoke(x, null);
return result as UIElement;
}
// Define other methods and classes here
static DockPanel GetDockPanel(FrameworkElement sender)
{
var child = GetTemplateChild(sender);
// if the frame has been drawn/nav enabled, child will be a border first
if (child is Border b)
{
child = b.Child;
}
var dp = child as DockPanel;
return dp;
}
static void FixArrowSize(Frame frame)
{
var dp = GetDockPanel(frame);
if (dp is null)
return;
var grid = dp.Children.OfType<Grid>().FirstOrDefault();
var path = grid.Children.OfType<System.Windows.Shapes.Path>().FirstOrDefault();
// we did it, we're going to be called multiple times, but only need to do our job once
if (path == null)
return;
grid.Children.Remove(path);
var size = 40.0;
grid.Children.OfType<Control>().ToList().ForEach(c =>
{
c.MinHeight = size;
c.MinWidth = size;
if (c is Button b)
{
var content = b.Content;
var child = GetTemplateChild(b) as Grid;
child.MinHeight = size;
child.MinWidth = size;
//} else if(c is Menu m)
//{
// var content = GetTemplateChild(m) as FrameworkElement;
// content.MinHeight = size;
// content.MinWidth = size;
}
});
var cd = grid.ColumnDefinitions;
cd[0].Width = new GridLength(size);
cd[1].Width = new GridLength(size);
// no row definitions
var rd = grid.RowDefinitions;
grid.MinHeight = size;
// see if you can see the current height/width of the column/rows and adjust the definitions, see if that changes the size
//frame
}
//
open
module Option =
let inline ofCast<'t> (x:obj) =
match x with
| :? 't as v -> Some v
| _ -> None
module Seq =
let inline ofType<'t> (items:_ seq) =
items |> Seq.choose(box >> Option.ofCast<'t>)
module WpfHelpers =
open System.Reflection
let getChildren (x:Panel) =
x.Children
let getChildrenOfType<'t> (x:Panel) : 't seq =
x
|> getChildren
|> Seq.cast<obj>
|> Seq.ofType<'t>
let getTemplateChild(x :FrameworkElement) =
let flags = BindingFlags.NonPublic ||| BindingFlags.Instance
let tcm = x.GetType().GetMember("get_TemplateChild", flags).[0] :?> MethodInfo
let result = tcm.Invoke(x,null)
result :?> UIElement
let getDockPanel (sender:FrameworkElement) =
// if the frame has been drawn/nav enabled, child will be a border first
let rec tryDP tryAgain (x:UIElement):DockPanel=
match x with
| :? Border as b ->
if tryAgain then
tryDP false b.Child
else
failwith "Border found inside border?"
| :? DockPanel as dp ->
dp
| null ->
invalidArg "sender" "No dockpanel, sender was null"
| x ->
x.Dump()
failwithf "that's no dockpanel, it's a %sstation!" <| x.GetType().Name
getTemplateChild sender
|> tryDP true
let fixArrowSize (frame:Frame) =
let adjustGridControl size (c:Control) =
c.MinHeight <- size
c.MinWidth <- size
c
|> Option.ofCast<Button>
|> Option.iter(fun b ->
let content = b.Content
let child = getTemplateChild b :?> Grid
child.MinHeight <- size
child.MinWidth <- size
)
match getDockPanel frame with
| null -> ()
| dp ->
let grid =
dp
|> getChildrenOfType<Grid>
|> Seq.head
grid
|> getChildrenOfType<System.Windows.Shapes.Path>
|> Seq.tryHead
|> Option.iter (fun path ->
grid.Children.Remove path
let size = 40.0
grid
|> getChildrenOfType<Control>
|> Seq.iter (adjustGridControl size)
)
()
let window = Window()
let generateDemoFrame gridRow =
let f = System.Windows.Controls.Frame()
f.NavigationUIVisibility <- System.Windows.Navigation.NavigationUIVisibility.Visible
let page =
Page(Content=Button(Content=sprintf "Hello from row %i (index %i)" gridRow (gridRow + 1)))
f.Navigate(page) |> ignore
f.SetValue(Grid.RowProperty,gridRow)
f
let frame2 = generateDemoFrame 2
let grid =
let g = Grid()
g.RowDefinitions.Add(RowDefinition(MinHeight=80.,Height=GridLength 80.))
g.RowDefinitions.Add(RowDefinition(Height=GridLength 200.))
g.RowDefinitions.Add(RowDefinition(Height=GridLength 200.))
generateDemoFrame 1
|> g.Children.Add
|> ignore<int>
g.Children.Add frame2 |> ignore<int>
g
window.Content <- grid
window.Dump()
// change size after display
WpfHelpers.fixArrowSize frame2
PresentationCore.dll
PresentationFramework.dll
System.Windows.Presentation.dll
WindowsBase.dll
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment